Chỉ mục MySQL - thực tiễn tốt nhất là gì?


208

Tôi đã sử dụng các chỉ mục trên cơ sở dữ liệu MySQL của tôi được một thời gian nhưng chưa bao giờ tìm hiểu đúng về chúng. Nói chung, tôi đặt một chỉ mục trên bất kỳ trường nào mà tôi sẽ tìm kiếm hoặc chọn bằng cách sử dụng WHEREmệnh đề nhưng đôi khi nó không có vẻ quá đen và trắng.

Các thực hành tốt nhất cho các chỉ mục MySQL là gì?

Ví dụ tình huống / tình huống khó xử:

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

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

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


5
Bạn có lẽ nên thử lại câu hỏi. Sự lựa chọn 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à theo quan điểm của tôi không liên quan đến php.
VGE


Câu trả lời:


242

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

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

Để đơ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, 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 đó trong một ứng dụng bảng tính rất thô sơ. Tất cả các bảng tính này hiện là hiển thị dữ liệu và đánh số các hàng theo thứ tự liên tiếp.

Bây giờ hãy tưởng tượng rằng bạn cần tìm tất cả các hàng có giá trị "M" trong cột thứ ba. Cho những gì bạn có sẵn, bạn chỉ có một lựa 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ó một chỉ mục. Chỉ số cụ thể này là chỉ số 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 một số thứ tự có ý nghĩa (giả sử theo bảng chữ cái) và cho mỗi giá trị, cung cấp một danh sách các số hàng nơi 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 trong đó giá trị của cột thứ ba là "M". Chẳng hạn, bạn có thể thực hiện tìm kiếm nhị phân ! Trong khi quét bảng yêu cầu bạn xem N hàng (trong đó N là số hàng), tìm kiếm nhị phân chỉ yêu cầu bạn xem các mục chỉ mục log-n, trong trường hợp xấu nhất. Wow, chắc chắn dễ dàng hơn 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 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 thêm một chút trong khi bạn đang viết các hàng mới, nhưng bạn tiết kiệm được rất nhiều thời gian khi bạn đang tìm kiếm thứ gì đó.

Vì vậy, nói chung, lập chỉ mục tạo ra sự đánh đổi giữa hiệu quả đọc và hiệu quả ghi. Không có chỉ mục, các phần chèn có thể rất nhanh - công cụ cơ sở dữ liệu chỉ cần 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 thao tác chèn.

Mặt khác, việc đọ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 tìm sự cân bằng 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 THÍCH, các công cụ lập chỉ mục thường sẽ giúp bạn tăng tốc độ đọc lên đến "%" đầu tiên. Nói cách khác, nếu bạn đang CHỌN cột WHERE THÍCH '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", sau đó cần quét các hàng trung gian đó để tìm tập hợp con có chứa "thanh". CHỌN ... cột WHERE THÍCH '% bar%' không thể sử dụng chỉ mục. Tôi hy vọng bạn có thể thấy tại sao.

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

Hy vọng rằng điều này sẽ giúp làm sáng tỏ một chút, nhưng tôi phải nhắc lại rằng tốt nhất bạn nên dành một vài giờ để tìm hiểu những bài viết hay giải thích những điều này một cách sâu sắc. Bạn cũng nên đọc tài liệu của 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à sử dụng bởi các nhà hoạch định truy vấn có thể thay đổi khá rộng rãi.


10
Còn các FULLTEXTchỉ số thì sao? Họ có thể giúp với điều kiện như thế LIKE '%bar%'nào?
Septagram 15/03/2016

2
@Septagram - FULLTEXTcó thể giúp với truy vấn đó nếu bar là "từ". FULLTEXTxử lý các từ, không phải các chuỗi con tùy ý (như LIKE).
Rick James

@timdev rõ ràng trong phần nào đã được trả lời câu hỏi đầu tiên? Tôi có thể phát hiện câu hỏi thứ hai và thứ ba được trả lời trong phần thứ nhất và thứ hai (trước và sau Hy vọng bao gồm hai câu hỏi đầu tiên của bạn ) về câu trả lời có giá trị của bạn
Manuel Jordan

1
@ManuelJordan - Không có câu trả lời đơn giản cho câu hỏi đầu tiên. Nó phụ thuộc vào cách bạn muốn cân bằng sự đánh đổi trong bối cảnh sử dụng dự đoán (hoặc thậm chí tốt hơn, được quan sát).
timdev

57

Kiểm tra các bài thuyết trình như Làm chủ thêm nghệ thuật lập chỉ mục .

Cập nhật 12/2012: Tôi đã đăng một bài thuyết trình mới của tôi: Cách thiết kế chỉ mục, thực sự . 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.

Thiết kế các chỉ mục tốt nhất là một quá trình phải phù hợp với các truy vấn bạn chạy trong ứng dụng của bạn.

Thật khó để đề xuất bất kỳ quy tắc mục đích chung nào về việc cột nào là tốt nhất để lập chỉ mục hoặc bạn có nên lập chỉ mục cho 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. Điều này phụ thuộc vào các truy vấn bạn cần chạy.

Có, có một số chi phí không cần thiết để bạn không cần tạo chỉ mục. 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í hoạt động của một chỉ số thường vượt xa lợi ích của nó.

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

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

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


3
Cảm ơn bạn rất nhiều. sl slideshoware.net/matsunobu/ thật sự rất hữu ích.
Bishal Paudel


1
Tuyệt vời trình chiếu sl.netare.net/billkarwin/how-to-design-indexes- trình bày thực tế
Manuel Jordan

1
Trình bày tuyệt vời (The from from 2012), thực sự hiểu toàn bộ quan điểm của chỉ số.
DarkteK

46

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

Chỉ số tổng hợp

Bạn có thể tạo các chỉ mục ghép - một chỉ mục bao gồm nhiều cột. MySQL có thể sử dụng chúng từ trái sang phải . Vì vậy, nếu bạn có:

Table A
Id
Name
Category
Age
Description

nếu bạn có một chỉ mục ghép bao gồm Tên / Danh mục / Tuổi theo thứ tự đó, các mệnh đề WHERE này sẽ sử dụng chỉ mục:

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ỉ số đó vì mọi thứ 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 chỉ số nào có sẵn cho MySQL và chỉ số nào thực sự chọn. MySQL sẽ chỉ sử dụng MỘT khóa cho mỗi truy vấn .

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

Nhật ký truy vấn chậm

Bật nhật ký truy vấn chậm để xem truy vấn nào đang chạy chậm.

Cột rộng

Nếu bạn có một cột rộng trong đó MOST của sự phân biệt xảy ra trong một vài ký tự đầu tiên, bạn chỉ có thể sử dụng N ký tự đầu tiên trong chỉ mục của mình. Ví dụ: Chúng tôi có một cột ReferenceNumber được định nghĩa là varchar (255) nhưng 97% 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á nhiều.


Tôi có một 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 bằng VARCHAR, bạn phải luôn đặt nó thành 255. Bây giờ bạn đã nói rằng một chỉ mục được đặt thành loại cột này có thể 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

20

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

Bạn đang tìm kiếm trên một trường theo cơ sở trường hoặc một số tìm kiếm sử dụng nhiều trường? Những lĩnh vực đang được tìm kiếm nhiều nhất trên? Các loại lĩnh vực là gì? (Chỉ mục hoạt động tốt hơn trên INTs so với trên VARCHAR chẳng hạn) Bạn đã thử sử dụng EXPLAIN trên các truy vấn đang được chạy chưa?

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

CẬP NHẬT và CHỨNG MINH sẽ chậm hơn. Ngoài ra còn có các yêu cầu không gian lưu trữ bổ sung, nhưng điều đó thường không quan trọng trong những ngày này.

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

Không, trừ khi đó là ĐỘC ĐÁO (có nghĩa là nó đã được lập chỉ mục) hoặc bạn chỉ tìm kiếm các kết quả khớp chính xác trên trường đó (không sử dụng tìm kiếm toàn văn bản của THÍCH hay myQuery).

Nói chung, tôi đặt một chỉ mục trên bất kỳ trường nào mà tôi sẽ tìm kiếm hoặc chọn bằng mệnh đề WHERE

Tôi thường lập chỉ mục các trường được truy vấn nhiều nhất và sau đó là INT / BOOLESE / ENUM thay vì các trường là VARCHARS. Đừng quên, thường thì bạn cần tạo một chỉ mục trên các trường kết hợp, thay vì 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.


11

Tải dữ liệu hiệu quả : Các chỉ mục tăng tốc độ truy xuất nhưng làm chậm việc chèn và xóa, cũng như cập nhật các giá trị trong các cột được lập 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ết. Điều này xảy ra bởi vì viết một hàng yêu cầu viết không chỉ hàng dữ liệu, nó cũng yêu cầu thay đổi đối với bất kỳ chỉ mục nào. Một bảng càng có nhiều 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 lần 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 các chỉ mục : Nếu bạn không cần một chỉ mục cụ thể để giúp các truy vấn hoạt động tốt hơn, đừng tạo nó.

Dung lượng ổ đĩa : Một chỉ mục chiếm không gian đĩa và nhiều chỉ mục chiếm nhiều 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 các chỉ số bất cứ nơi nào có thể.

Takeaway: Đừng quá chỉ số


5

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

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

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

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

(b) Độ chọn lọc của các cột đó là bao nhiêu (có bao nhiêu giá trị riêng biệt được lưu trữ, so với tổng số lượng 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.

Các tác động hiệu suất khó khăn của việc lập chỉ mục là gì?

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

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

Hãy thử chỉ số FULLTEXT .


4

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

3) sử dụng một chỉ mục toàn văn hoặc có thể là nhân sư


Để ngăn chặn slow down other operations like insert, update and deletesbạn có thể sử dụng START TRANSACTION; YOUR CODE HERE; COMMIT Điều này có thể giúp tránh slowing downcác hoạt động khác, vì nó sẽ chỉ kiểm tra một trong các ràng buộc một lần. Nên biết trước: Nếu bạn sử dụng REPLACE INTOvà bạn SQL_MODE<> STRICT_ALL_TABLESHOẶC TRADITIONALCác Bulk Loadsẽ bỏ qua các thay thế vào và chèn các bản sao.
JayRizzo

Giao dịch không được hỗ trợ trong tất cả các công cụ MySQL. AFAIK, các giao dịch làm chậm hoạt động DB, ngay cả khi chúng chỉ được sử dụng ngầm. Những gì chúng ta cần thiết kế dựa trên hiệu suất thực tế là một số cách bán tự động (đo lường hiệu suất) của các lựa chọn tối ưu hóa khác nhau, bao gồm các chỉ mục và giao dịch.
David Spector
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.