2012-02-07 27 views
7

Tôi có một chỉ mục trên một cột nullable và tôi muốn chọn tất cả các giá trị của nó như thế này:Index cho cột nullable

SELECT e.ename 
FROM emp e; 

Trong kế hoạch giải thích tôi thấy một FULL TABLE SCAN (thậm chí là một gợi ý không hiệu quả)

SELECT e.ename 
FROM emp e 
WHERE e.ename = 'gdoron'; 

Liệu sử dụng chỉ số ...

tôi googled và phát hiện ra không có mục null trong chỉ số, do đó truy vấn đầu tiên không thể sử dụng các chỉ số.

Câu hỏi của tôi rất đơn giản: tại sao không có mục nhập rỗng trong chỉ mục?

+1

Như một sang một bên, toàn bộ bảng có thể được thực hiện trong ví dụ đầu tiên của bạn khi bạn đang chọn một tỷ lệ lớn các bản ghi từ bảng (trong trường hợp của bạn, 100%). Cho dù bạn có chỉ số giá trị Null hay không không quan trọng thì người tối ưu hóa đã chọn tham gia FTS cho truy vấn này. – Ollie

+0

@Ollie. Đây là lý do tại sao tôi đã viết rằng tôi đã thử nó một lần nữa với một gợi ý 'và nó đã không giúp đỡ ... – gdoron

+1

tốt, điển hình b-tree chỉ số sẽ không bao gồm nulls. Chỉ mục bitmap sẽ lập chỉ mục null. – tbone

Trả lời

14

Theo mặc định, cơ sở dữ liệu quan hệ bỏ qua giá trị NULL (vì mô hình quan hệ nói rằng NULL có nghĩa là "không hiện diện"). Vì vậy, chỉ số không lưu trữ giá trị NULL, do đó nếu bạn có điều kiện null trong câu lệnh SQL, chỉ mục liên quan được bỏ qua (theo mặc định).

Nhưng bạn có thể gây ra vấn đề này, hãy kiểm tra THIS hoặc THIS bài viết.

+0

Tôi đọc bài viết này, đây là lý do tại sao tôi hỏi tại sao điều này lại hoạt động theo cách này. Thật kỳ lạ. – gdoron

+1

Hãy nghĩ về điều này, trong một chỉ mục làm thế nào chúng có thể khác biệt với tất cả các NULL? –

2

Nếu bạn đang nhận được tất cả các hàng trong bảng, tại sao bạn cho rằng nó nên sử dụng chỉ mục? Quét toàn bộ bảng là phương tiện hiệu quả nhất để trả về tất cả các giá trị. Nó không có gì để làm với các null không được trong chỉ mục và tất cả mọi thứ để làm với trình tối ưu hóa chọn phương tiện hiệu quả nhất để lấy dữ liệu.


@ A.B.Cade: Có thể trình tối ưu hóa có thể chọn sử dụng chỉ mục, nhưng không có khả năng. Giả sử bạn có một bảng với một bảng được lập chỉ mục với 100 hàng, nhưng chỉ có 10 giá trị. Nếu trình tối ưu hóa sử dụng chỉ mục, nó phải lấy 10 hàng từ chỉ mục, sau đó mở rộng nó thành 100 hàng, trong khi đó, với quá trình quét toàn bộ bảng, nó sẽ nhận được tất cả 100 hàng từ get-go. Dưới đây là ví dụ:

create table test1 (blarg varchar2(10)); 

create index ak_test1 on test1 (blarg); 

insert into test1 
select floor(level/10) from dual connect by level<=100; 

exec dbms_stats.gather_table_stats('testschema','test1'); 

exec dbms_stats.gather_index_stats('testschema','ak_test1'); 

EXPLAIN PLAN FOR 
select * from test1; 

Vấn đề của tôi phần lớn là dựa trên một tiền đề thiếu sót: quét chỉ mục thực chất tốt hơn là quét toàn bộ bảng. Điều đó không phải lúc nào cũng đúng, như kịch bản này chứng minh.

+0

xem nhận xét của DaveCosta. Anh ta đang truy vấn cột chỉ mục - nếu không cho các giá trị rỗng, nó sẽ sử dụng một INDEX FULL SCAN –

+0

Vâng, chúng ta không thể nói rằng nó chắc chắn sẽ sử dụng chỉ mục, chỉ là nó có thể có. –

+0

Tôi đồng ý, nhưng anh ấy đã nêu trong câu hỏi "(thậm chí một gợi ý không giúp được)" –

0

Tôi không chắc chắn truy vấn đầu tiên là thích hợp về mặt sử dụng chỉ mục, ít nhất là thứ hai có thể.

Dù sao, trong khi đó là sự thật mà bạn có thể không chỉ một cột chứa giá trị null, có nhiều cách để làm điều đó như ví dụ:

create index MY_INDEX on emp(ename, 1); 

thông báo các , 1) vào cuối mà hiện các trick.

+0

Ý bạn không phải là: 'tạo chỉ mục MY_INDEX trên emp (NVL (ename, 'null')); ' – gdoron

+0

nope. dấu phẩy tiếp theo là chữ số 1 là dạng đúng. mà không cần sử dụng nvl. nvl là một thủ thuật khác để sử dụng nó nhưng nó buộc người dùng phải so sánh với chuỗi 'null' nếu được sử dụng như bạn đã viết nó. – Farid

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