2009-07-07 31 views
9

Giả sử tôi có một bảng cơ sở dữ liệu với các cột a, b và c. Tôi có kế hoạch thực hiện truy vấn trên cả ba cột, nhưng tôi không chắc chắn về các cột cụ thể mà tôi đang truy vấn. Có đủ các hàng trong bảng mà một chỉ số vô cùng tăng tốc độ tìm kiếm, nhưng nó cảm thấy sai lầm khi làm cho tất cả các hoán vị của các chỉ số có thể (như thế này):Có cách nào tốt hơn để lập chỉ mục nhiều cột hơn tạo chỉ mục cho mỗi hoán vị không?

a 
b 
c 
a, b 
a, c 
b, c 
a, b, c 

Có cách nào tốt hơn để xử lý vấn đề này? (Rất có thể tôi sẽ chỉ lập chỉ mục tốt, a, b, c thôi, vì điều này sẽ cắt giảm số hàng nhanh chóng, nhưng tôi tự hỏi nếu có cách nào tốt hơn.)

Nếu bạn cần ví dụ cụ thể hơn, trong dữ liệu thực tế, các cột là thành phố, tiểu bang và mã zip. Ngoài ra, tôi đang sử dụng một cơ sở dữ liệu MySQL.

Trả lời

19

Trong MS SQL, chỉ mục "a, b, c" sẽ bao gồm các trường hợp "a"; "a, b"; và "a, b, c". Vì vậy, bạn chỉ cần các chỉ mục sau:

a, b, c 
b, c 
c 

Không chắc chắn nếu MySQL hoạt động theo cùng một cách, nhưng tôi sẽ giả định như vậy.

+7

Đây là câu trả lời đúng. MySQL hoạt động theo cùng một cách, và kỹ thuật này được gọi là "Tiền tố tận cùng bên trái". Từ hướng dẫn sử dụng MySQL tại http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html: "Nếu bảng có chỉ mục nhiều cột, thì bất kỳ tiền tố ngoài cùng nào của chỉ mục có thể được sử dụng bởi Ví dụ, nếu bạn có chỉ mục ba cột trên (col1, col2, col3), bạn đã lập chỉ mục các khả năng tìm kiếm trên (col1), (col1, col2) và (col1, col2, col3) " – zombat

+0

Hmm, tôi nên biết điều này. ;) Rất tuyệt vời, tôi sẽ thực hiện cú đánh này. –

+1

Bạn cũng có thể cần một, c, nhưng nó phụ thuộc vào các truy vấn của bạn trông như thế nào.Bạn cũng có thể cần chỉ mục riêng lẻ để bao gồm kịch bản OR được đề cập bởi Andriyev, không chắc chắn. –

1

Càng nhiều chỉ mục bạn tạo, hiệu suất của bạn sẽ càng bị ảnh hưởng trong quá trình cập nhật và xóa hoạt động. Vì bản thân chỉ mục có thể được cập nhật.

Có, bạn có thể sử dụng chỉ mục nhiều cột. Một cái gì đó như

CREATE TABLE temp (
    id   INT NOT NULL, 
    a   INT NULL, 
    b   INT NULL, 
    c   INT NULL, 
    PRIMARY KEY (id), 
    INDEX ind1 (a,b,c), 
    INDEX ind2 (a,b) 
); 

Đây là loại chỉ số tức là ind1 chắc chắn sẽ giúp bạn trong các truy vấn như

SELECT * FROM temp WHERE a=2 AND b=3 AND c=4; 

Tương tự, ind2 sẽ giúp bạn trong các truy vấn như

SELECT * FROM temp WHERE a=2 AND b=3; 

Nhưng những chỉ số thắng' t được sử dụng nếu truy vấn là một số thứ như

SELECT * FROM temp WHERE a=2 OR b=3 OR c=4; 

Ở đây bạn sẽ cần các chỉ mục riêng biệt trên a, b và c. Vì vậy, thay vì có quá nhiều chỉ mục, tôi đồng ý với những gì John nói tức là có chỉ mục trên a, b, c và nếu bạn cảm thấy khối lượng công việc của mình bao gồm nhiều truy vấn nhiều cột hơn thì bạn có thể chuyển sang chỉ mục nhiều cột .

cổ vũ

+0

Bảng này hiếm khi được cập nhật, vì vậy không có gì đáng lo ngại đối với tôi nếu cập nhật chậm. –

1

Cho rằng các cột của bạn là thực sự thành phố, Nhà nước và Zip Code, tôi sẽ đề nghị chỉ các chỉ số sau:

INDEX (mã bưu điện)

Nếu tôi đúng, Zip Mã không được nhân đôi trên khắp nước Mỹ, do đó, nó vô nghĩa thêm thông tin thành phố hoặc tiểu bang cho chỉ mục cũng bởi vì họ sẽ có cùng giá trị cho tất cả các mã Zip. Ví dụ: 90210 luôn là Los Angeles, CA.

INDEX (City (5)) hoặc INDEX (City (5)), Nhà nước)

Đây chỉ là một chỉ số trên năm chữ cái đầu tiên của tên thành phố.Trong nhiều trường hợp, điều này sẽ đủ cụ thể để có chỉ mục State sẽ không cung cấp bất kỳ tính năng lọc hữu ích nào. Ví dụ: 'Los A' gần như chắc chắn sẽ là hồ sơ từ Los Angeles, CA. Có lẽ có một thị trấn nhỏ khác ở Mỹ bắt đầu với 'Los A', nhưng sẽ có quá ít hồ sơ không đáng để làm lộn xộn chỉ mục với dữ liệu của Nhà nước. Mặt khác, một số tên thành phố xuất hiện ở nhiều bang (Springfield đến với tâm trí), vì vậy trong những trường hợp đó, tốt hơn là nên có Nhà nước được lập chỉ mục. Bạn sẽ cần phải tìm ra cho chính mình chỉ mục nào phù hợp nhất với bộ dữ liệu của bạn. Nếu nghi ngờ, tôi sẽ đi với chỉ số thứ hai (Thành phố và Tiểu bang).

INDEX (Nhà nước, sort_field)

Nhà nước là một chỉ số khá rộng (hoàn toàn có thể NY và CA mình sẽ có 30% số hồ sơ). Nếu bạn có kế hoạch trình bày thông tin này cho người sử dụng, ví dụ, 30 hồ sơ cùng một lúc, sau đó bạn sẽ có một truy vấn kết thúc bằng

... WHERE STATE = "NY" 
ORDER BY <sort_field> 
LIMIT <number>, 30 

Để làm rằng truy vấn hiệu quả, bạn cần bao gồm cột sắp xếp trong Chỉ mục trạng thái. Vì vậy, nếu bạn đang hiển thị các trang được sắp xếp theo Họ (giả sử bạn có cột đó), thì bạn sẽ sử dụng INDEX (Tiểu bang, Họ (3)), nếu không, MySQL phải sắp xếp tất cả của hồ sơ 'NY' trước đó nó có thể cung cấp cho bạn 30 bạn muốn.

+2

Thông tin của bạn về mã ZIP không chính xác. Nhiều mã ZIP có nhiều "tên địa điểm được chấp nhận". Ví dụ: "Hollywood, CA" là tên địa điểm chấp nhận được cho 90028, mặc dù Hollywood chỉ là một quận của Los Angeles chứ không phải là thành phố thực tế. "Tên địa điểm mặc định" cho 90028 thực sự là "Los Angeles, CA". Đồng thời, đôi khi hai thành phố hoặc một phần của hai thành phố sẽ nằm trong cùng một mã ZIP. Đúng là mỗi mã ZIP có chính xác một "tên địa điểm mặc định", nhưng bạn không thể dựa vào đó cho dữ liệu do người dùng nhập. – Geerad

+0

Miễn là có (trong hầu hết các trường hợp) không quá hai hoặc ba tên địa điểm cho mỗi Mã Zip, chỉ mục vẫn sẽ ổn. –

+0

Không chắc chắn tỷ lệ phần trăm là bao nhiêu, nhưng mã zip của tôi có bốn tên cho phép. Và tôi biết người khác cũng có bốn người. –

1

Tùy thuộc vào truy vấn sql của bạn.

chỉ mục (a, b, c) là khác nhau để chỉ mục (b, c, a) hoặc chỉ số (a, c, b)

4

Để sử dụng các chỉ số cho tất cả các điều kiện bình đẳng càng tốt trên N cột, bạn sẽ cần C([N/2], N) chỉ số, đó là N!/([N/2]! * (N - [N/2])!)

Xem bài viết này trong blog của tôi để giải thích chi tiết:

Bạn cũng có thể đọc các chặt chẽ toán học proof bởi Nga toán học Egor Timoshenko (update: bây giờ trong tiếng Anh).

ai có thể, tuy nhiên, có được hiệu suất đàng hoàng với chỉ số ít sử dụng các kỹ thuật sau:

Index sáp nhập

Nếu các cột col1, col2col3 là chọn lọc, sau đó truy vấn này

SELECT * 
FROM mytable 
WHERE col1 = :value1 
     AND col2 = :value2 
     AND col3 = :value3 

có thể sử dụng ba chỉ mục riêng biệt trên col1, col2col3, chọn 's ROWID phù hợp với từng điều kiện riêng biệt và họ tìm ngã tư của họ, như trong:

SELECT * 
FROM (
     SELECT rowid 
     FROM mytable 
     WHERE col1 = :value1 
     INTERSECT 
     SELECT rowid 
     FROM mytable 
     WHERE col2 = :value2 
     INTERSECT 
     SELECT rowid 
     FROM mytable 
     WHERE col3 = :value3 
     ) mo 
JOIN mytable mi 
ON  mi.rowid = mo.rowid 

Bitmap indexing

PostgreSQL có thể xây dựng các chỉ số bitmap tạm thời trong bộ nhớ ngay trong truy vấn.

Chỉ mục bitmap là một mảng bit liền kề nhỏ gọn.

Mỗi bit được đặt cho mảng cho biết rằng việc sửa lỗi tid phải được chọn từ bảng.

Chỉ mục như vậy có thể mất nhưng 128M lưu trữ tạm thời cho một bảng có 1G hàng.

Các truy vấn sau đây:

SELECT * 
FROM mytable 
WHERE col1 = :value1 
     AND col2 = :value2 
     AND col3 = :value3 

đầu tiên sẽ phân bổ một bitmap zero-điền đủ lớn để trang trải tất cả các khả năng tid 's trong bảng (có nghĩa là đủ lớn để thực hiện tất cả tid' s từ (0, 0) đến cuối cùng, không bị mất tích tid vào tài khoản).

Sau đó, nó sẽ tìm kiếm chỉ mục đầu tiên, thiết lập các bit thành 1 nếu chúng thỏa mãn điều kiện đầu tiên.

Sau đó, nó sẽ quét chỉ mục thứ hai, AND 'ing các bit thỏa mãn điều kiện thứ hai với 1. Điều này sẽ để lại 1 chỉ cho những bit thỏa mãn cả hai điều kiện.

Tương tự cho chỉ mục thứ ba.

Cuối cùng, nó sẽ chỉ chọn các hàng tương ứng với các bit của tid.

Số tid sẽ được tìm nạp liên tục, vì vậy nó rất hiệu quả.

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