2011-11-17 27 views
5

Tôi đã học về các chỉ mục trong Oracle SQL và tôi muốn tiến hành một thử nghiệm nhỏ với một bảng thử nghiệm để xem các chỉ mục thực sự hoạt động như thế nào. Như tôi đã khám phá từ một bài viết trước đó được thực hiện ở đây, cách tốt nhất để làm điều này là với EXPLAIN PLAN. Tuy nhiên, tôi đang chạy vào một cái gì đó mà confuses tôi.Chỉ mục, GIẢI THÍCH KẾ HOẠCH và truy cập bản ghi trong Oracle SQL

Bảng mẫu của tôi chứa các thuộc tính (EmpID, Fname, Lname, Occupation, .... etc). Tôi phổ biến nó với 500.000 hồ sơ bằng cách sử dụng một chương trình java tôi đã viết (tên ngẫu nhiên, nghề nghiệp, vv). Bây giờ, sau đây là một số truy vấn mẫu có và không có chỉ số:

NO INDEX:

SELECT Fname FROM EMPLOYEE WHERE Occupation = 'DOCTOR'; 

giải thích kế hoạch nói:

OPERATION       OPTIMIZER COST 
TABLE ACCESS(FULL) TEST.EMPLOYEE ANALYZED 1169 

Bây giờ tôi có thể tạo chỉ mục:

CREATE INDEX occupation_idx 
    ON EMPLOYEE (Occupation); 

VỚI INDEX "occupation_idx":

SELECT Fname FROM EMPLOYEE WHERE Occupation = 'DOCTOR'; 

giải thích kế hoạch nói:

OPERATION       OPTIMIZER COST 
TABLE ACCESS(FULL) TEST.EMPLOYEE ANALYZED 1169 

... Vì vậy, chi phí vẫn như cũ, 1169? Bây giờ tôi cố gắng này:

VỚI INDEX "occupation_idx":

SELECT Occupation FROM EMPLOYEE WHERE Occupation = 'DOCTOR'; 

giải thích kế hoạch nói:

OPERATION        OPTIMIZER COST 
INDEX(RANGE SCAN) TEST.OCCUPATION_IDX ANALYZED 67 

Vì vậy, dường như chỉ số chỉ được sử dụng khi cột đó là người duy nhất Tôi đang kéo giá trị từ. Nhưng tôi nghĩ rằng điểm của một chỉ số là để mở khóa toàn bộ bản ghi bằng cách sử dụng cột được lập chỉ mục làm khóa? Việc tìm kiếm ở trên là một điều vô nghĩa ... nó tìm kiếm các giá trị mà bạn đã biết. Truy vấn đáng giá duy nhất tôi có thể nghĩ về cái nào CHỈ liên quan đến giá trị của một cột được lập chỉ mục (và không phải là phần còn lại của bản ghi) sẽ là tổng hợp như COUNT hay cái gì đó.

Tôi đang thiếu gì?

+0

Câu hỏi thú vị, tôi sẽ tò mò muốn biết tại sao điều này xảy ra. – ChandlerPelhams

+0

Khóa chính có được định nghĩa cho bảng 'EMPLOYEE' không? –

+0

Có thể chỉ số chưa hoàn thành xây dựng? nếu bạn chạy lại truy vấn SELECT Fname FROM EMPLOYEE WHERE Occupation = 'DOCTOR'; chi phí của nó giảm? – xQbert

Trả lời

5

Ngay cả với chỉ mục của bạn, Oracle đã quyết định thực hiện quét toàn bộ truy vấn thứ hai.

Tại sao lại thực hiện việc này? Oracle sẽ tạo ra hai kế hoạch và đưa ra một chi phí cho mỗi: -

1) Full scan

2) truy cập Index

Oracle chọn phương án với chi phí thấp hơn. Rõ ràng nó đã đưa ra toàn bộ quá trình quét với chi phí thấp hơn.

Nếu bạn muốn xem chi phí của kế hoạch chỉ mục, bạn có thể làm một giải thích kế hoạch với một gợi ý như thế này để buộc việc sử dụng chỉ số:

SELECT /*+ INDEX(EMPLOYEE occupation_idx) */ Fname 
FROM EMPLOYEE WHERE Occupation = 'DOCTOR'; 

Nếu bạn một giải thích kế hoạch trên, bạn sẽ thấy rằng chi phí lớn hơn chi phí quét toàn bộ. Đây là lý do tại sao Oracle không chọn sử dụng chỉ mục.

Một cách đơn giản để xem xét chi phí của kế hoạch chỉ số là: -

  • Các blevel của chỉ số (có bao nhiêu khối phải được đọc từ trên xuống dưới)
  • Số khối bảng sau đó phải đọc cho các bản ghi phù hợp trong chỉ mục. Điều này dựa trên ước tính của Oracle về số lượng nhân viên có sự chiếm đóng của 'DOCTOR'. Trong ví dụ đơn giản của bạn, điều này sẽ là:

    số hàng/số giá trị khác biệt

cân nhắc More phức tạp bao gồm các nhà máy phân nhóm và chỉ số điều chỉnh chi phí mà cả hai phản ánh mất ổn định mà một khối được đọc đã có trong bộ nhớ và do đó không cần phải đọc từ đĩa.

lẽ bạn có thể cập nhật câu hỏi của bạn với kết quả từ truy vấn của bạn với những gợi ý chỉ số và cũng là kết quả của truy vấn này: -

SELECT COUNT(*), COUNT(DISTINCT(Occupation)) 
FROM EMPLOYEE; 

Điều này sẽ cho phép mọi người nhận xét về chi phí của kế hoạch chỉ mục.

+0

Cảm ơn bạn đã trả lời. Tôi không bao giờ biết về "gợi ý". Tuy nhiên, nó dường như không hoạt động. Ngay cả với gợi ý đó, nó vẫn quét toàn bộ, giống như không có gợi ý. – The111

+0

@Johnson: Tôi đã có gợi ý sai. Xem chỉnh sửa. –

+0

Cảm ơn gợi ý đã sửa. Khi tôi tạo bảng của mình, tôi cố ý tạo tập lệnh ngẫu nhiên có một miền có kích thước khác nhau cho mỗi trường. Ví dụ, trường lname chọn từ 500 lnames trong khi trường fname chọn từ chỉ 100. Tôi biết các biến thể này sẽ rất thú vị để phân tích cuối cùng. Sử dụng các gợi ý bây giờ tôi có thể xác định chính xác miền kích thước mà chỉ mục trở nên đáng giá để sử dụng (ngẫu nhiên, khi miền có khoảng 450 giá trị có thể ... hoặc đặt một cách khác: khi các hàng được tìm thấy bằng tài khoản chỉ mục dưới 0,2% của bảng). – The111

0

Là một WAG. Phân tích bảng và chỉ mục, sau đó xem liệu kế hoạch có thay đổi hay không.

Khi bạn chỉ chọn nghề nghiệp, toàn bộ truy vấn có thể được đáp ứng từ chỉ mục. Chỉ số theo nghĩa đen có một bản sao của nghề nghiệp. Thời điểm bạn thêm một cột bổ sung cho lựa chọn, Oracle phải đi đến bản ghi dữ liệu, để lấy nó. Trình tối ưu hóa chọn đọc tất cả các hàng dữ liệu thay vì tất cả các hàng chỉ mục và các hàng dữ liệu. Nó rẻ hơn.

+0

Không may mắn. Cảm ơn mặc dù. – The111

+0

Sau đó, quét toàn bộ bảng là cách rẻ hơn để thực hiện. Chúng ta đang nói về loại dữ liệu nào? – EvilTeach

+0

Thêm một mũi tên khác vào bộ rung của bạn. Tìm hiểu cách sử dụng AUTOTRACE với SQLPLUS. http://www.adp-gmbh.ch/ora/sqlplus/autotrace.html – EvilTeach

2

Một chỉ số là bản sao của bảng mà chỉ lưu trữ các dữ liệu sau:

  • lĩnh vực Indexed (s)
  • Một con trỏ tới dòng gốc (rowid).

Giả sử bạn có một bảng như thế này:

rowid id name occupation 
[1]  1 John clerk 
[2]  2 Jim manager 
[3]  3 Jane boss 

Sau đó, một chỉ mục trên occupation sẽ trông như thế này:

occupation rowid 
boss  [3] 
manager  [2] 
clerk  [1] 

, với các hồ sơ được sắp xếp trên occupation trong một B-Tree.

Như bạn thấy, nếu bạn chỉ chọn các trường được lập chỉ mục, bạn chỉ cần chỉ mục (bảng thứ hai).

Nếu bạn chọn bất cứ điều gì khác hơn là occupation:

SELECT * 
FROM mytable 
WHERE occupation = 'clerk' 

sau đó động cơ nên làm hai điều: thứ nhất tìm các hồ sơ có liên quan trong chỉ mục, thứ hai, tìm các bản ghi trong bảng ban đầu bằng cách rowid. Nó giống như nếu bạn tham gia hai bảng trên rowid.

Vì các hàng trong chỉ mục không theo thứ tự nên các lần đọc tới bảng gốc không tuần tự và có thể chậm. Nó có thể nhanh hơn để đọc bảng gốc theo thứ tự tuần tự và chỉ lọc các bản ghi với occupation = 'clerk'.

Động cơ không "mở khóa" các bản ghi: nó chỉ tìm thấy hàng trong chỉ mục và nếu không có đủ dữ liệu trong chỉ mục, tìm kiếm dữ liệu trong bảng gốc theo số rowid được tìm thấy.

3

Tôi nghĩ rằng tôi thấy điều gì đang xảy ra ở đây.

Khi bạn có chỉ số tại chỗ, và bạn làm:

SELECT Occupation FROM EMPLOYEE WHERE Occupation = 'DOCTOR'; 

Các kế hoạch thực hiện sẽ sử dụng các chỉ số. Điều này là không có trí tuệ, gây ra tất cả các dữ liệu cần thiết để đáp ứng các truy vấn là phải có trong chỉ mục, và Oracle thậm chí không bao giờ phải tham khảo bảng ở tất cả.

Tuy nhiên, khi bạn làm:

SELECT Fname FROM EMPLOYEE WHERE Occupation = 'DOCTOR'; 

sau đó, nếu Oracle sử dụng các chỉ số, nó sẽ làm một SCAN INDEX PHẠM VI tiếp theo là một TABLE TIẾP CẬN THEO ROWID để tìm kiếm các fname tương ứng với đó Nghề nghiệp. Bây giờ, tùy thuộc vào bao nhiêu hàng có DOCTOR cho nghề nghiệp, Oracle sẽ phải thực hiện một hoặc nhiều chuyến đi đến bảng, để tìm kiếm các Fname. Ví dụ, nếu bạn có một bảng, và tất cả các nhân viên có Nghề nghiệp được đặt thành 'DOCTOR', thì chỉ mục đó không được sử dụng nhiều, và Oracle sẽ chỉ làm một TABLE ĐẦY ĐỦ của bảng. Nếu có 10.000 nhân viên, và chỉ có một người là DOCTOR, thì một lần nữa, nó không có trí tuệ, và Oracle sẽ sử dụng chỉ mục.

Nhưng có một số sự tinh tế, khi bạn ở đâu đó giữa hai thái cực đó. Mọi người thích nói về 'chọn lọc', nghĩa là, có bao nhiêu hàng được chỉ định bởi chỉ mục, so với kích thước của bảng, khi thảo luận liệu chỉ mục đó có được sử dụng hay không. Tuy nhiên, đó không phải là thực sự là đúng. Những gì Oracle thực sự quan tâm là khối chọn lọc. Đó là, có bao nhiêu khối phải truy cập, để đáp ứng truy vấn? Vì vậy, đầu tiên, làm thế nào "rộng" là RANGE SCAN? Giới hạn phạm vi giá trị được chỉ định bởi các giá trị vị ngữ càng hạn chế thì càng tốt. Thứ hai, khi truy vấn của bạn cần thực hiện tra cứu bảng, có bao nhiêu khối khác nhau sẽ phải truy cập để tìm tất cả dữ liệu cần thiết. Tức là, dữ liệu "ngẫu nhiên" như thế nào trong bảng liên quan đến thứ tự chỉ mục? Điều này được gọi là CLUSTERING_FACTOR. Nếu bạn phân tích chỉ mục để thu thập số liệu thống kê và sau đó xem USER_INDEXES, bạn sẽ thấy rằng CLUSTERING_FACTOR hiện đã được điền.

Vậy, CLUSTERING_FACTOR là gì? CLUSTERING_FACTOR là "trật tự" của bảng, liên quan đến (các) cột chính của chỉ mục. Giá trị của CLUSTERING_FACTOR sẽ luôn nằm giữa số khối trong bảng và số hàng trong bảng. Một thấp CLUSTERING_FACTOR, tức là một số rất gần với số lượng khối trong bảng, biểu thị một bảng được sắp xếp theo thứ tự, liên quan đến chỉ mục. Một cao CLUSTERING_FACTOR, tức là, một con số rất gần với số lượng hàng trong bảng, rất không có thứ tự, liên quan đến chỉ mục.

Đó là một khái niệm quan trọng để hiểu rằng CLUSTERING_FACTOR mô tả thứ tự dữ liệu trong bảng liên quan đến chỉ mục.Vì vậy, việc xây dựng lại một chỉ mục, chẳng hạn, sẽ không thay đổi CLUSTERING_FACTOR. Điều quan trọng là phải hiểu rằng cùng một bảng có thể có hai chỉ mục và một bảng có thể có CLUSTERING_FACTOR tuyệt vời và bảng kia có thể có CLUSTERING_FACTOR cực kỳ kém. Bản thân bảng chỉ có thể được sắp xếp theo một cách.

Vì vậy, tại sao tôi đã dành quá nhiều thời gian mô tả CLUSTERING_FACTOR? Bởi vì khi bạn có một kế hoạch thực hiện thực hiện một INDEX RANGE SCAN theo sau là TABLE ACCESS BY ROWID, bạn có thể chắc chắn rằng CLUSTERING_FACTOR đã được xem xét bởi trình tối ưu hóa của Oracle, để đưa ra kế hoạch thực hiện. Ví dụ: giả sử bạn có một bảng hàng 10.000 và giả sử 100 hàng có Occupation = 'DOCTOR'. Bạn viết truy vấn ở trên, yêu cầu Fname của nhân viên có nghề nghiệp là DOCTOR. Vâng, Oracle có thể dễ dàng và hiệu quả xác định các hàng của các hàng mà nghề nghiệp là DOCTOR. Tuy nhiên, có bao nhiêu khối bảng mà Oracle cần truy cập, để thực hiện tra cứu Fname? Nó có thể chỉ là 1 hoặc 2 khối bảng, nếu dữ liệu được nhóm lại (theo thứ tự) bởi nghề nghiệp trong bảng. Nhưng, nó có thể lên đến 100, nếu dữ liệu không được sắp xếp trong bảng! Vì vậy, một lần nữa, 10.000 bảng hàng, và, giả sử, (với mục đích minh họa và toán học đơn giản) rằng bảng có 100 hàng/khối, và như vậy, 100 khối. Tùy thuộc vào thứ tự bảng (tức là CLUSTERING_FACTOR), số lần truy cập khối bảng có thể chỉ bằng 1 hoặc nhiều nhất là 100.

Vì vậy, tôi hy vọng điều này sẽ giúp bạn hiểu tại sao trình tối ưu hóa có thể miễn cưỡng sử dụng chỉ mục trong vài trường hợp.

+0

+1 chi tiết hữu ích! –

Các vấn đề liên quan