2009-09-18 39 views
21

Bạn có cần tạo chỉ mục cho các trường nhóm theo các trường trong cơ sở dữ liệu Oracle không?Tạo chỉ mục cho nhóm theo trường?

Ví dụ:

select * 
from some_table 
where field_one is not null and field_two = ? 
group by field_three, field_four, field_five 

tôi đã được thử nghiệm các chỉ số tôi đã tạo cho ở trên và chỉ số có liên quan chỉ cho truy vấn này là một chỉ số được tạo ra cho field_two. Các chỉ mục đơn hoặc tổng hợp khác được tạo trên bất kỳ trường nào khác sẽ không được sử dụng cho truy vấn trên. Điều này có đúng không?

Trả lời

11

Điều này có thể đúng, nhưng điều đó phụ thuộc vào lượng dữ liệu bạn có. Thông thường tôi sẽ tạo chỉ mục cho các cột tôi đã sử dụng trong GROUP BY, nhưng trong trường hợp của bạn, trình tối ưu hóa có thể đã quyết định rằng sau khi sử dụng chỉ mục field_two sẽ không có đủ dữ liệu được trả về để biện minh bằng cách sử dụng chỉ mục khác cho GROUP BY.

+1

+1 để đề cập đến trình tối ưu hóa, đây có thể là nguyên nhân có khả năng nhất của việc này. –

+0

Cảm ơn bạn đã phản hồi. Tôi không nhận ra kế hoạch giải thích phụ thuộc vào lượng dữ liệu trong bảng. Hiện không có dữ liệu nào trong bảng, điều này giải thích tại sao trình tối ưu hóa có thể đã bỏ qua các chỉ mục khác. Trên một lưu ý khác, chỉ mục tổng hợp trên field_three và field_four không có field_five vẫn được sử dụng trong truy vấn giống như ở trên? Điều này sẽ không bao gồm tất cả các trường trong nhóm theo mệnh đề. – onejigtwojig

+0

@Mark - giải thích điều đó. Xem các chỉnh sửa của tôi để biết thêm thông tin về những chỉ mục mà Oracle có thể sử dụng cho nhóm. –

7

Không, điều này có thể không chính xác.

Nếu bạn có một bảng lớn, Oracle có thể thích phát sinh các trường từ chỉ mục hơn là từ bảng, thậm chí không có chỉ mục duy nhất bao gồm tất cả các giá trị.

Trong bài viết mới nhất trong blog của tôi:

, có một truy vấn trong đó Oracle không sử dụng đầy đủ bảng quét nhưng thay vì tham gia hai chỉ số để có được các giá trị cột:

SELECT l.id, l.value 
FROM t_left l 
WHERE NOT EXISTS 
     (
     SELECT value 
     FROM t_right r 
     WHERE r.value = l.value 
     ) 

Kế hoạch này là:

SELECT STATEMENT 
HASH JOIN ANTI 
    VIEW , 20090917_anti.index$_join$_001 
    HASH JOIN 
    INDEX FAST FULL SCAN, 20090917_anti.PK_LEFT_ID 
    INDEX FAST FULL SCAN, 20090917_anti.IX_LEFT_VALUE 
    INDEX FAST FULL SCAN, 20090917_anti.IX_RIGHT_VALUE 

Như bạn có thể thấy, không có TABLE SCAN trên t_left tại đây.

Thay vào đó, Oracle mất các chỉ số trên idvalue, gia nhập chúng trên rowid và nhận được (id, value) cặp từ kết quả tham gia.

Bây giờ, để truy vấn của bạn:

SELECT * 
FROM some_table 
WHERE field_one is not null and field_two = ? 
GROUP BY 
     field_three, field_four, field_five 

Thứ nhất, nó sẽ không biên dịch, vì bạn đang chọn * từ một bảng với một điều khoản GROUP BY.

Bạn cần thay thế * bằng các biểu thức dựa trên các cột nhóm và tổng hợp của các cột không nhóm.

Bạn có lẽ hầu hết sẽ được hưởng lợi từ các chỉ số sau:

CREATE INDEX ix_sometable_23451 ON some_table (field_two, field_three, field_four, field_five, field_one) 

, vì nó sẽ chứa tất cả mọi thứ cho cả lọc trên field_two, phân loại trên field_three, field_four, field_five (hữu dụng cho GROUP BY) và đảm bảo rằng field_oneNOT NULL.

+1

Rất thú vị - Tôi không nghĩ rằng tôi đã từng thấy trước đó (nơi Oracle sẽ tham gia hai chỉ mục và tránh toàn bộ bảng) –

+0

'@Eric Petroelje': có một gợi ý đặc biệt,' INDEX_JOIN', để ép buộc phương thức này . – Quassnoi

2

Bạn có cần tạo chỉ mục cho các trường nhóm theo trường trong cơ sở dữ liệu Oracle không?

Không. Bạn không cần, theo nghĩa là truy vấn sẽ chạy bất kể có chỉ mục tồn tại hay không. Các chỉ mục được cung cấp để cải thiện hiệu suất truy vấn.

Tuy nhiên, có thể trợ giúp; nhưng tôi ngần ngại thêm một chỉ mục chỉ để giúp một truy vấn, mà không suy nghĩ về tác động có thể có của chỉ mục mới trên cơ sở dữ liệu.

... chỉ mục có liên quan cho truy vấn này là chỉ mục được tạo cho field_two. Các chỉ mục đơn hoặc tổng hợp khác được tạo trên bất kỳ trường nào khác sẽ không được sử dụng cho truy vấn trên. Điều này có đúng không?

Không phải lúc nào. Thường thì GROUP BY sẽ yêu cầu Oracle thực hiện một loại (nhưng không phải lúc nào); và bạn có thể loại bỏ hoạt động sắp xếp bằng cách cung cấp một chỉ mục phù hợp trên (các) cột được sắp xếp.

Dù bạn thực sự cần phải lo lắng về hiệu suất GROUP BY, tuy nhiên, là một câu hỏi quan trọng để bạn suy nghĩ.

+0

upvote cho "có thể loại bỏ hoạt động sắp xếp ..". BTW bài viết này có thêm chi tiết http://use-the-index-luke.com/sql/sorting-grouping/indexed-group-by – waltersu

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