2012-11-18 41 views
8

Tôi đã được thông báo rằng nếu bạn biết bạn sẽ thường xuyên sử dụng một trường để tham gia, có thể là tốt để tạo chỉ mục trên đó.Khi nào cần thêm chỉ mục vào trường bảng SQL (MySQL)?

Tôi thường hiểu khái niệm lập chỉ mục một bảng (giống như một chỉ mục trong một cuốn sách giấy cho phép bạn tra cứu một thuật ngữ cụ thể mà không phải tìm kiếm từng trang). Nhưng tôi ít rõ ràng hơn về thời điểm sử dụng chúng.

Giả sử tôi có 3 bảng: bảng USERS, COMMENTS và VOTES. Và tôi muốn tạo một chuỗi bình luận giống như Stackoverflow, trong đó truy vấn trả về các nhận xét cũng như các số phiếu tăng/giảm trên các nhận xét đó.

USERS table 
user_id user_name 
1   tim 
2   sue 
3   bill 
4   karen 
5   ed 

COMMENTS table 
comment_id topic_id comment commenter_id 
1   1  good job!   1 
2   2  nice work   2 
3   1  bad job :)  3 

VOTES table 
vote_id vote comment_id voter_id 
    1   -1  1   5 
    2   1  1   4 
    3   1  3   1 
    4   -1  2   5 
    5   1  2   4 

Here's the query and SQLFiddle to return the votes on topic_id=1:

select u.user_id, u.user_name, 
    c.comment_id, c.topic_id, c.comment, 
    count(v.vote) as totals, sum(v.vote > 0) as yes, sum(v.vote < 0) as no, 
    my_votes.vote as did_i_vote 
from comments c 
join users u on u.user_id = c.commenter_id 
left join votes v on v.comment_id = c.comment_id 
left join votes my_votes on my_votes.comment_id = c.comment_id 
and my_votes.voter_id = 1 
where c.topic_id = 1 
group by c.comment_id, u.user_name, c.comment_id, c.topic_id, did_i_vote; 

Giả sử số lượng comment và phiếu đi vào hàng triệu. Để tăng tốc truy vấn, câu hỏi của tôi là tôi nên đặt chỉ mục trên comments.commenter_id, votes.voter_idvotes.comment_id?

+1

Sử dụng chúng khi tăng tốc truy vấn. –

+0

@SteveWellens bạn có thể cung cấp mã SQL để thêm các chỉ mục thích hợp vào câu trả lời và/hoặc trong [SQLFiddle] (http://www.sqlfiddle.com/#!2/b562a/13) không? –

+1

Bạn cũng cần phải thêm chỉ mục vào 'topic_id'. – Skpd

Trả lời

3

Dưới đây là một bản cập nhật với một số phím mà quen http://www.sqlfiddle.com/#!2/94daa/1

Động cơ có để so sánh chi phí của việc sử dụng một chỉ số với chi phí không làm như vậy. Bạn sẽ nhận thấy tôi đã phải thêm một số hàng vào để có được các chỉ mục được sử dụng.

Với chỉ mục, công cụ phải sử dụng chỉ mục để nhận các giá trị phù hợp, nhanh chóng. Sau đó, nó phải sử dụng các kết quả phù hợp để tra cứu các hàng thực tế trong bảng. Nếu chỉ mục không thu hẹp số hàng, nó có thể nhanh hơn để tìm kiếm tất cả các hàng trong bảng.

Tôi không chắc liệu mysql có tương tự như chỉ mục nhóm SQL Server hay không. Trong trường hợp này dữ liệu chỉ mục và bảng trong cùng một cấu trúc, do đó bạn không có bước thứ hai của việc tìm kiếm chỉ mục.

Tôi đã giới thiệu các chỉ mục theo hai cách khác nhau, trước tiên trên bảng người dùng bằng cách xác định khóa chính. Điều này sẽ ngầm tạo ra một chỉ mục duy nhất trên cột user_id. Một chỉ mục duy nhất có nghĩa là nếu bạn không thể chèn cùng một tập hợp các giá trị hai lần. Đối với chỉ mục cột đơn, điều này chỉ có nghĩa là bạn không thể có cùng một giá trị hai lần.

Nếu bạn tưởng tượng một cuốn sách người dùng cho bảng, với một người dùng trên mỗi trang, thì chỉ mục được tạo sẽ cung cấp cho bạn danh sách user_id được sắp xếp, mỗi danh sách có số trang của người dùng. Danh sách này thường được lưu trữ trong một số loại hình cây để tìm kiếm một số cụ thể nhanh chóng. Hãy nghĩ về cách bạn tra cứu tên trong sổ điện thoại, bạn không chỉ quét tất cả các trang cho đến khi bạn tìm thấy nó, bạn đoán xem nó sẽ ở đâu, và sau đó bỏ qua hoặc chuyển tiếp các phần của trang cho đến khi bạn đến gần . Bạn thường có thể tra cứu các giá trị trong một chỉ mục trong thời gian O (log n), trong đó n là số hàng và bạn cần phải đọc một số trang chỉ mục tương tự.

Bây giờ nếu động cơ DB được cung cấp truy vấn select * from users Where user_id = 3, nó có hai lựa chọn. nó có thể đọc từng trang dữ liệu và tìm giá trị phù hợp (nó có thể sử dụng thực tế có khóa chính để dừng ở đầu tiên). Cách khác là đọc chỉ mục để có được trang dữ liệu phù hợp và sau đó tìm kiếm trang dữ liệu.

Để biết cụ thể và đơn giản, giả sử bảng có 1024 mục nhập. Giả sử mỗi mục nhập có một trang dữ liệu. Giả sử mỗi mục nhập trong cây chỉ mục có một trang chỉ mục. Giả sử chỉ số được cân bằng, vì vậy nó có 10 cấp độ và tổng số 2047 trang.(tất cả các giả định này đều là nghi ngờ, nhưng chúng nhận được điểm, trong các trang chỉ mục hầu như luôn nhỏ hơn các trang dữ liệu, vì bạn không có xu hướng lập chỉ mục tất cả các cột cùng một lúc).

Để thực hiện, phương pháp quét bảng sẽ yêu cầu đọc 1024 trang dữ liệu. Để sử dụng chỉ mục sẽ yêu cầu đọc 10 trang chỉ mục và một trang dữ liệu. Hầu như tất cả các hiệu suất cơ sở dữ liệu là về việc giảm thiểu số lượng trang đã đọc.

Chỉ mục nhiều cột cho phép tìm kiếm nhanh chóng các tập hợp dữ liệu. Nếu bạn có một chỉ mục với (col1, col2), thậm chí chỉ cần kết hợp trên col1 được cải thiện.

Tuyên bố create index chỉ cho biết cột nào được lập chỉ mục và có cho phép giá trị trùng lặp hay không.

Sử dụng lại cuốn sách tương tự, Create Index ix_comment_id on votes (comment_id, voter_id) sẽ tạo danh sách thứ tự của comment_id rồi voter_id với tham chiếu đến hàng dữ liệu tương ứng.

+------------+--------------+---------+ 
| comment_id | reference_id | row_ref | 
+------------+--------------+---------+ 
|   1 |   4 | ref1 | 
|   1 |   5 | ref2 | 
|   2 |   4 | ref3 | 
|   2 |   5 | ref4 | 
|   3 |   1 | ref5 | 
+------------+--------------+---------+ 
+0

- @ Laurence, tôi phải bước ra trong 2 giờ nhưng tôi sẽ kiểm tra mã của bạn sau đó và bình luận về nó, cảm ơn câu trả lời của bạn! –

+0

Tôi muốn chấp nhận câu trả lời của bạn nhưng để hoàn thành, trước tiên bạn có thể thêm vào câu trả lời của bạn một lời giải thích cho phần 'TẠO INDEX' của mã của bạn không? –

+1

@timpeterson Đã thêm một số giải thích khác. – Laurence

15

Không phải lúc nào cũng được cắt rõ ràng khi sử dụng chỉ mục trong bảng SQL. Nhưng có một số quy tắc chung của ngón tay cái có thể giúp bạn quyết định trong hầu hết các trường hợp.

  1. index Đặt trên các cột đang được sử dụng ở nơi khoản
  2. index Đặt trên các cột mà bạn sử dụng để tham gia vào.
  3. Cố gắng không sử dụng nhiều hơn 4-5 chỉ mục trên các cột trong cùng một bảng.

Và các khái niệm chung mà bạn nên lưu ý là:

  1. Bất kỳ chỉ số mà bạn sử dụng sẽ thực hiện tìm kiếm trên những cột nhanh hơn.
  2. Bất kỳ chỉ mục nào bạn thêm sẽ khiến việc chèn bảng này chậm hơn một chút.
  3. Từ hai trang trước. Bạn có trách nhiệm quyết định số lần chèn và truy vấn bạn thực hiện trên bảng để quyết định xem có nên sử dụng chỉ mục và cột nào hay không.

EDIT

@AndrewLazarus bình luận thực sự quan trọng và tôi quyết định thêm nó vào câu trả lời:

  1. Không sử dụng các chỉ số trên các cột chỉ với vài giá trị khác nhau. Ví dụ: một cột chứa trạng thái, khi chỉ có một vài trạng thái hoặc giá trị boolean. Lý do không làm như vậy là chỉ số không thực sự giúp bạn vì chỉ số này sẽ được chia cho số lượng giá trị và vì bạn chỉ có một vài giá trị, nên sẽ không có bất kỳ lợi ích thực sự nào. Bảng sẽ tiêu thụ nhiều không gian hơn với chỉ mục và biểu mẫu phôi chậm hơn khi chèn, nhưng bạn sẽ không nhận được hiệu suất tốt hơn đáng kể khi truy vấn
+0

- @ goBeepit dev, cảm ơn, có thể bạn thêm vào câu trả lời của bạn một số mã để thêm các chỉ số xây dựng mã tôi đang sử dụng/SQLFiddle? –

+1

Ngoài ra, đừng bận tâm với các chỉ mục trên các cột chỉ mất một vài giá trị rời rạc. –

+0

@AndrewLazarus, vì vậy điều này có nghĩa là không đặt chỉ mục trên cột 'phiếu bầu' (giá trị = -1 hoặc 1) nhưng đặt một cột vào cột 'xxx_id' (trong đó giá trị = 1-> vô cực)? –

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