2010-06-15 90 views
162

Tôi đã sử dụng các chỉ mục trên cơ sở dữ liệu MySQL của mình một thời gian nhưng chưa bao giờ đúng cách đã học được về chúng. Nói chung tôi đặt một chỉ mục trên bất kỳ lĩnh vực mà tôi sẽ được tìm kiếm hoặc lựa chọn bằng cách sử dụng một khoản WHERE nhưng đôi khi nó không có vẻ như vậy là màu đen và trắng.Chỉ mục MySQL - các phương pháp hay nhất là gì?

Thực tiễn tốt nhất cho chỉ mục MySQL là gì?

Ví dụ tình huống/vấn đề nan giải:

Nếu một bảng có sáu cột và tất cả các họ có thể tìm kiếm, nên tôi chỉ tất cả trong số họ hoặc ai trong số họ?

.

Hiệu suất tiêu cực Tác động của việc lập chỉ mục là gì?

.

Nếu tôi có cột VARCHAR 2500 mà có thể tìm kiếm được từ các phần của trang web, tôi có nên lập chỉ mục không?

+3

Có lẽ bạn nên gắn thẻ lại câu hỏi. Việc lựa chọn các chỉ mục là một phần quan trọng để tối ưu hóa bất kỳ mô hình cơ sở dữ liệu nào. Và quan điểm của tôi không liên quan đến php. – VGE

Trả lời

8

Load dữ liệu hiệu quả: Chỉ số tăng tốc khả năng tìm lại nhưng chậm chèn và xóa, cũng như cập nhật các giá trị trong các cột được đánh chỉ mục. Đó là, các chỉ mục làm chậm hầu hết các hoạt động liên quan đến việc viết. Điều này xảy ra vì việc viết một hàng đòi hỏi phải viết không chỉ dòng dữ liệu, nó cũng đòi hỏi phải thay đổi bất kỳ chỉ mục nào. Càng có nhiều bảng chỉ mục, càng cần phải thực hiện nhiều thay đổi và sự suy giảm hiệu suất trung bình càng lớn. Hầu hết các bảng nhận được nhiều lần đọc và ít ghi, nhưng đối với một bảng có tỷ lệ ghi cao, chi phí cập nhật chỉ mục có thể là đáng kể.

Tránh chỉ mục: Nếu bạn không cần chỉ mục cụ thể để giúp truy vấn hoạt động tốt hơn, đừng tạo.

Không gian đĩa: Chỉ mục chiếm dung lượng đĩa và nhiều chỉ mục chiếm thêm không gian tương ứng. Điều này có thể khiến bạn đạt đến giới hạn kích thước bảng nhanh hơn nếu không có chỉ mục. Tránh chỉ mục bất cứ khi nào có thể.

Takeaway: Không quá index

3

1/2) Chỉ số tăng tốc độ nhất định chọn hoạt động nhưng họ làm chậm các hoạt động khác như chèn, cập nhật và xóa dần. Nó có thể là một sự cân bằng tốt.

3) sử dụng một chỉ mục văn bản đầy đủ hoặc có lẽ Sphinx

+0

Để ngăn chặn 'làm chậm các hoạt động khác như chèn, cập nhật và xóa' bạn có thể sử dụng ' BẮT ĐẦU GIAO DỊCH; ' ' MÃ ĐÂY CỦA BẠN TẠI ĐÂY; ' ' COMMIT' . nó sẽ chỉ kiểm tra một ràng buộc một lần. CAVEAT: Nếu bạn sử dụng 'REPLACE INTO' và' SQL_MODE' <> 'STRICT_ALL_TABLES' HOẶC' TRADITIONAL' 'Tải trọng hàng loạt 'sẽ bỏ qua thay thế và chèn các bản sao. – JayRizzo

19

Nếu một bảng có sáu cột và tất cả trong số họ có thể tìm kiếm, nên tôi chỉ mục tất cả trong số họ hoặc ai trong số họ

Are bạn đang tìm kiếm trên cơ sở từng trường hoặc là một số tìm kiếm sử dụng nhiều trường? Trường nào là nhất đang được tìm kiếm? Các loại trường là gì? (Chỉ số hoạt động tốt hơn trên INTs so với VARCHAR chẳng hạn) Bạn đã thử sử dụng GIẢI THÍCH về các truy vấn đang được chạy chưa?

những tác động hiệu suất negetive của indexing

cập nhật và chèn sẽ chậm hơn là gì. Ngoài ra còn có những yêu cầu không gian lưu trữ thêm, nhưng đó là điều không quan trọng thường ngày trong những ngày này.

Nếu tôi có một VARCHAR 2500 cột đó là tìm kiếm từ các bộ phận của trang web của tôi, nên tôi chỉ nó

Không, trừ khi đó là UNIQUE (có nghĩa là nó đã được lập chỉ mục) hoặc bạn chỉ tìm kiếm chính xác đối sánh trên trường đó (không sử dụng tìm kiếm toàn văn của LIKE hoặc mySQL).

Nói chung tôi đặt một chỉ mục trên bất kỳ lĩnh vực mà tôi sẽ được tìm kiếm hoặc lựa chọn sử dụng một mệnh đề WHERE

Tôi thường chỉ số các lĩnh vực được các truy vấn nhất, và sau đó INTs/Booleans/ENUM thay vì các trường đó là VARCHARS. Đừng quên, thông thường bạn cần tạo chỉ mục trên các trường kết hợp, chứ không phải chỉ mục trên một trường riêng lẻ. Sử dụng GIẢI THÍCH, và kiểm tra nhật ký chậm.

42

Xem bản trình bày như More Mastering the Art of Indexing.

Cập nhật 12/2012: Tôi đã đăng bản trình bày mới của tôi: How to Design Indexes, Really. Tôi đã trình bày điều này vào tháng 10 năm 2012 tại ZendCon ở Santa Clara, và vào tháng 12 năm 2012 tại Percona Live London.

Việc thiết kế các chỉ mục tốt nhất là quy trình phải khớp với các truy vấn bạn chạy trong ứng dụng của mình. Thật khó để đề xuất bất kỳ quy tắc chung nào về các cột nào là tốt nhất để lập chỉ mục hoặc bạn nên lập chỉ mục tất cả các cột, không có cột, chỉ mục nào sẽ trải rộng trên nhiều cột, v.v. .

Có, có một số chi phí để bạn không nên tạo chỉ mục một cách không cần thiết. Nhưng bạn nên tạo các chỉ mục mang lại lợi ích cho các truy vấn bạn cần để chạy nhanh. Chi phí của chỉ số thường vượt xa so với lợi ích của nó.

Đối với một cột đó là VARCHAR (2500), có thể bạn muốn sử dụng một FULLTEXT index hay một chỉ số tiền tố:

CREATE INDEX i ON SomeTable(longVarchar(100)); 

Lưu ý rằng một chỉ số thông thường không thể giúp đỡ nếu bạn đang tìm kiếm những từ mà có thể ở giữa của varchar dài đó. Đối với điều đó, hãy sử dụng chỉ mục toàn văn.

+2

Cảm ơn bạn rất nhiều. http://www.slideshare.net/matsunobu/more-mastering-the-art-of-indexing?next_slideshow=1 thực sự rất hữu ích. – RY35

37

tôi sẽ không lặp lại một số lời khuyên tốt trong câu trả lời khác, nhưng sẽ bổ sung thêm:

Compound Chỉ số

Bạn có thể tạo các chỉ số hợp chất - một chỉ số bao gồm nhiều cột. MySQL có thể sử dụng chúng từ bên trái đến ngay.Vì vậy, nếu bạn có:

Table A 
Id 
Name 
Category 
Age 
Description 

nếu bạn có một chỉ số hợp chất bao gồm Tên/loại/Tuổi theo thứ tự đó, những mệnh đề WHERE sẽ sử dụng các chỉ số:

WHERE Name='Eric' and Category='A' 

WHERE Name='Eric' and Category='A' and Age > 18 

nhưng

WHERE Category='A' and Age > 18 

sẽ không sử dụng chỉ mục đó vì mọi thứ đều phải được sử dụng từ trái sang phải.

Giải thích

Sử dụng Giải thích/Giải thích mở rộng để hiểu những gì chỉ số có sẵn để MySQL và cái nào nó thực sự lựa chọn. MySQL sẽ chỉ sử dụng ONE khóa cho mỗi truy vấn.

EXPLAIN EXTENDED SELECT * from Table WHERE Something='ABC' 

Slow Query Log

Bật slow query log để xem truy vấn đang chạy chậm.

Cột Wide

Nếu bạn có một cột rộng nơi mà hầu hết sự khác biệt xảy ra trong vài ký tự đầu tiên, bạn có thể chỉ sử dụng các nhân vật N đầu tiên trong chỉ số của bạn. Ví dụ: Chúng tôi có một cột ReferenceNumber được định nghĩa là varchar (255) nhưng 97% các trường hợp, số tham chiếu là 10 ký tự trở xuống. Tôi đã thay đổi chỉ mục để chỉ nhìn vào 10 ký tự đầu tiên và cải thiện hiệu suất khá một chút.

+0

Tôi có câu hỏi về phần cuối cùng. Tôi đọc ở đâu đó rằng nếu bạn tạo một cột với VARCHAR, bạn nên luôn đặt nó là 255. Bây giờ bạn đã nói rằng một chỉ mục được đặt cho loại cột này có thể bị giới hạn chỉ nhìn vào 10 ký tự đầu tiên. Làm thế nào chính xác bạn có thể làm điều đó? – AlexioVay

+0

Tác vụ 'WHERE Name = 'Eric' and Age> 18' có hoạt động ở đâu không? –

188

Bạn chắc chắn nên dành chút thời gian đọc về lập chỉ mục, có rất nhiều bài viết về nó và điều quan trọng là phải hiểu những gì đang diễn ra.

Nói chung và chỉ mục áp đặt thứ tự trên các hàng của bảng.

Vì mục đích đơn giản, hãy tưởng tượng một bảng chỉ là một tệp CSV lớn. Bất cứ khi nào một hàng được chèn vào, nó được chèn vào cuối. Vì vậy, thứ tự "tự nhiên" của bảng chỉ là thứ tự các hàng được chèn vào.

Hãy tưởng tượng bạn đã tải tệp CSV đó vào một ứng dụng bảng tính rất thô sơ. Tất cả bảng tính này là hiển thị dữ liệu và đánh số các hàng theo thứ tự tuần tự.

Bây giờ hãy tưởng tượng rằng bạn cần phải tìm tất cả các hàng có một số giá trị "M" trong cột thứ ba. Với những gì bạn có sẵn, bạn chỉ có một tùy chọn. Bạn quét bảng kiểm tra giá trị của cột thứ ba cho mỗi hàng. Nếu bạn có nhiều hàng, phương pháp này ("quét bảng") có thể mất nhiều thời gian!

Bây giờ hãy tưởng tượng rằng ngoài bảng này, bạn đã có chỉ mục. Chỉ mục cụ thể này là chỉ mục của các giá trị trong cột thứ ba. Chỉ mục liệt kê tất cả các giá trị từ cột thứ ba, theo thứ tự có ý nghĩa (nói theo thứ tự bảng chữ cái) và cho mỗi giá trị, cung cấp danh sách các số hàng có giá trị đó xuất hiện.

Bây giờ bạn có một chiến lược tốt để tìm tất cả các hàng có giá trị của cột thứ ba là "M". Ví dụ: bạn có thể thực hiện binary search!Trong khi quét bảng yêu cầu bạn xem xét các hàng N (trong đó N là số hàng), tìm kiếm nhị phân chỉ yêu cầu bạn nhìn vào các mục nhập chỉ mục log-n, trong trường hợp rất xấu nhất. Wow, điều đó chắc chắn dễ hơn rất nhiều! Tất nhiên, nếu bạn có chỉ mục này, và bạn đang thêm các hàng vào bảng (cuối cùng, vì đó là cách mà bảng khái niệm của chúng tôi hoạt động), bạn cần cập nhật chỉ mục mỗi lần. Vì vậy, bạn làm một công việc nhiều hơn một chút trong khi bạn đang viết hàng mới, nhưng bạn tiết kiệm rất nhiều thời gian khi bạn đang tìm kiếm một cái gì đó.

Vì vậy, nói chung, việc lập chỉ mục tạo ra sự cân bằng giữa hiệu quả đọc và hiệu quả viết. Không có chỉ mục, chèn có thể rất nhanh - công cụ cơ sở dữ liệu chỉ thêm một hàng vào bảng. Khi bạn thêm chỉ mục, công cụ phải cập nhật từng chỉ mục trong khi thực hiện chèn.

Mặt khác, lần đọc trở nên nhanh hơn rất nhiều.

Hy vọng rằng bao gồm hai câu hỏi đầu tiên của bạn (như những người khác đã trả lời - bạn cần phải tìm số dư phù hợp).

Kịch bản thứ ba của bạn phức tạp hơn một chút. Nếu bạn đang sử dụng LIKE, các công cụ lập chỉ mục thường sẽ giúp bạn tăng tốc độ đọc lên "%" đầu tiên. Nói cách khác, nếu bạn đang chọn WHERE cột LIKE 'foo% bar%', cơ sở dữ liệu sẽ sử dụng chỉ mục để tìm tất cả các hàng nơi cột bắt đầu bằng "foo", và sau đó cần phải quét các hàng trung gian đó để tìm tập hợp con có chứa "bar". SELECT ... WHERE cột LIKE '% bar%' không thể sử dụng chỉ mục. Tôi hy vọng bạn có thể thấy lý do tại sao.

Cuối cùng, bạn cần bắt đầu nghĩ về các chỉ mục trên nhiều cột. Khái niệm này là như nhau, và hành xử tương tự như các công cụ LIKE - thiết yếu, nếu bạn có một chỉ mục trên (a, b, c), động cơ sẽ tiếp tục sử dụng chỉ mục từ trái sang phải tốt nhất có thể. Vì vậy, tìm kiếm trên cột a có thể sử dụng chỉ mục (a, b, c), như chỉ mục một (a, b). Tuy nhiên, động cơ sẽ cần quét toàn bộ bàn nếu bạn đang tìm kiếm WHERE b = 5 AND c = 1)

Hy vọng điều này sẽ giúp giảm bớt ánh sáng, nhưng tôi phải nhắc lại rằng bạn nên bỏ ra một vài giờ đào xung quanh cho các bài viết tốt giải thích những điều này trong chiều sâu. Bạn cũng nên đọc tài liệu về máy chủ cơ sở dữ liệu cụ thể của mình. Cách các chỉ số được thực hiện và được sử dụng bởi các nhà lập kế hoạch truy vấn có thể thay đổi khá rộng rãi.

+8

Còn các chỉ mục 'FULLTEXT' thì sao? Họ có thể giúp đỡ với các điều kiện như 'LIKE '% bar%'' không? – Septagram

4

Nói chung, các chỉ mục giúp tìm kiếm cơ sở dữ liệu tăng tốc, có bất lợi khi sử dụng dung lượng đĩa bổ sung và làm chậm các truy vấn INSERT/UPDATE/DELETE. Sử dụng EXPLAIN và đọc kết quả để tìm hiểu khi nào MySQL sử dụng chỉ mục của bạn.

Nếu bảng có sáu cột và tất cả đều có thể tìm kiếm được, tôi có nên lập chỉ mục tất cả hoặc không có cột nào trong số chúng?

Lập chỉ mục tất cả sáu cột không phải lúc nào cũng là phương pháp hay nhất.

(a) Bạn có sử dụng bất kỳ cột nào trong số những cột đó khi tìm kiếm thông tin cụ thể không?

(b) Độ chọn lọc của các cột đó (số lượng giá trị riêng biệt được lưu trữ, so với tổng số bản ghi trên bảng)?

MySQL sử dụng trình tối ưu hóa dựa trên chi phí, cố gắng tìm đường dẫn "rẻ nhất" khi thực hiện truy vấn. Và các lĩnh vực có chọn lọc thấp không phải là ứng cử viên tốt.

Tác động hiệu suất negetive của việc lập chỉ mục là gì?

Đã trả lời: không gian đĩa bổ sung, hiệu suất thấp hơn trong khi chèn - cập nhật - xóa.

Nếu tôi có cột VARCHAR 2500 có thể tìm kiếm được từ các phần của trang web, tôi có nên lập chỉ mục không?

Hãy thử FULLTEXT Index.

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