2011-07-21 32 views
16

Tôi có một bảng mà tôi làm chủ yếu cập nhật và tôi tự hỏi nếu các truy vấn cập nhật sẽ được hưởng lợi từ việc có chỉ mục trên cột ở đâu và cột được cập nhật hoặc chỉ mục trên cột ở đâu?Truy vấn cập nhật mysql có được hưởng lợi từ chỉ mục không?

+2

Chỉ mục trên cột trong 'WHERE' (có thể) sẽ giúp ích. Có lẽ có nghĩa là nó sẽ giúp ích nếu nó có thể giúp 'SELECT' tương đương. Ví dụ: nếu bạn có điều kiện 'WHERE id> 3' và gần như tất cả các id là> 3, thì chỉ mục sẽ không được sử dụng. –

+0

Về phần thứ hai của câu hỏi, chỉ mục trên '(wherecolumn, updatedcolumn)' cũng có thể giúp ích. Nhưng tôi nghĩ rằng chỉ vì MySQL kiểm tra và không làm một bản cập nhật trong giá trị cập nhật là giống với giá trị hiện tại của cột. Vì vậy, 'UPDATE t SET a = 7 WHERE grp = 47' có thể bennefit tạo thành một chỉ mục' (grp, a) 'nếu có nhiều hàng với' grp = 47' và 'a' đã bằng' 7'. –

+0

Bạn đang sử dụng công cụ lưu trữ nào, cấu trúc của bảng là gì và truy vấn cập nhật là gì? Tất cả những điều này có thể tạo nên sự khác biệt cho câu trả lời. – Mike

Trả lời

13

Chỉ trên cột vị trí. Chỉ mục trên cột cập nhật sẽ thực sự làm chậm truy vấn của bạn vì chỉ mục phải được cập nhật cùng với dữ liệu. Chỉ mục trên cột nơi sẽ tăng tốc độ cập nhật và chọn, nhưng làm chậm một số chèn.

Chỉ mục cũng gây ra phí khi bạn xóa các hàng. Nói chung, họ là một điều tốt mặc dù trên cột bạn đang sử dụng WHERE trên rất nhiều và về cơ bản là cần thiết trên các cột bạn tham gia hoặc ORDER BY

+1

Việc cập nhật một chỉ mục được thực hiện hoàn toàn trong bộ nhớ khá nhanh. Truy vấn cập nhật là truy vấn đơn giản tăng một cột. Tôi tự hỏi nếu việc thêm cột thứ hai vào chỉ mục sẽ phụ thêm một giá trị đọc để tìm giá trị ban đầu. – incognito2

+0

Đó là một câu hỏi hay. Tôi nghĩ rằng trình tối ưu hóa MySQL sẽ tận dụng lợi thế của chỉ mục, nhưng thật khó để nói. Bạn luôn có thể bật hồ sơ và thử cả hai truy vấn và xem liệu bạn có nhận thấy bất kỳ điều gì không. – Paulpro

7

Không phải là câu trả lời thẳng cho câu trả lời này. Vì vậy, ở đây đi.

UPDATE table SET ColumnA = 'something' 

nếu chỉ mục tồn tại trên ColumnA thì bạn sẽ có hiệu suất nhỏ khi có hai thao tác ghi cho mỗi hàng. Đầu tiên là dữ liệu trong bảng và sau đó viết để cập nhật chỉ mục.
Bạn thậm chí có thể có một số chỉ mục mà mỗi chỉ mục có ColumnA như là một phần của chỉ mục có nghĩa là bạn sẽ có nhiều lần viết cùng với hàng của bảng. Bạn có thể thấy làm thế nào có nhiều hơn một vài chỉ mục có thể bắt đầu thực sự làm chậm cập nhật của bạn xuống.
Nhưng nếu ColumnA không được lập chỉ mục, thì nó sẽ là một ghi duy nhất cho mỗi hàng.

UPDATE table SET ColumnA = 'something' WHERE ColumnB = 'something else' 

Đối với truy vấn này nếu một chỉ mục tồn tại trên cộtB và không phải trên ColumnA, sẽ rất nhanh để định vị bản ghi (gọi là tìm kiếm) và một lần viết để cập nhật và vì chỉ mục không quan tâm về columnA, nó sẽ không cần cập nhật.
Nhưng nếu bạn chỉ mục ColumnA và không ColumnB, Bạn sẽ đọc từng hàng trong bảng đầu tiên (gọi là quét và thường là một điều xấu) trong khi đọc nhanh hơn ghi vẫn còn rất chậm, sau đó nó sẽ ghi vào bảng và sau đó viết cho chỉ mục. Về cơ bản cách làm chậm nhất.

DELETE table WHERE ColumnB = 'somethingelse' 

Bây giờ nếu bạn có chỉ mục trên bất kỳ cột nào trong bảng này hai viết, xóa khỏi bảng và cập nhật/xóa bản ghi trong chỉ mục.
Một lần nữa nếu ColumnB không được lập chỉ mục, bạn sẽ quét bảng sau đó xóa (các) hàng khỏi bảng và cập nhật các chỉ mục nếu có.

INSERT INTO table (ColumnA, ColumnB) VALUES ('something','something else') 

Nếu không có chỉ mục tồn tại, một lần ghi vào bảng và được thực hiện.
Một lần nữa, nếu các chỉ mục tồn tại, thì ghi thêm cho mỗi chỉ mục.

Tôi chưa đề cập đến các ràng buộc chính của khóa chính, bởi vì bạn thực sự không thể gặp chúng khi bạn cần khóa chính, nhưng mỗi bản ghi phải được kiểm tra để xem có điều gì đó đã tồn tại với khóa đó trước khi chèn hay không. Đó sẽ là một chỉ số khóa chính nhanh chóng tìm kiếm, nhưng tuy nhiên, đó là một bước tiến khác trong quá trình này. Các bước càng ít thì càng nhanh.

Bây giờ hãy quay lại trang của bạn, Về cơ bản, nếu bạn cần cập nhật một bản ghi cụ thể, chỉ mục sẽ giúp bạn xác định bản ghi đó nhanh hơn quét toàn bộ bảng. Thời gian lưu để định vị bản ghi sẽ nhiều hơn sau đó thời gian mất cập nhật các chỉ mục. Nếu bạn chỉ chèn và không bao giờ đọc thì chỉ mục sẽ làm chậm bạn xuống. Nó trở thành một sự cân bằng. Nếu bạn cần đọc các bản ghi cụ thể, thì chỉ mục sẽ giúp vô cùng. Nhưng càng nhiều chỉ mục, thì tốc độ ghi càng chậm.

+0

Bạn đang đề cập đến công cụ lưu trữ nào trong câu trả lời? – Mike

+0

Câu trả lời hay nhất tại đây. Cảm ơn bạn! –

12

Hầu hết mọi người ở đây không biết chỉ mục hoạt động như thế nào trong MySQL.

Tùy thuộc vào công cụ lưu trữ bạn đang sử dụng. InnoDB sử dụng các chỉ mục hoàn toàn khác với MyISAM. Điều này là do MySQL triển khai các chỉ mục trên mức công cụ lưu trữ mức không phải cấp độ máy chủ MySQL.

Tôi sợ hầu hết mọi người ở đây đang cung cấp cho bạn câu trả lời dựa trên cơ sở dữ liệu khác trong đó chỉ mục hoạt động khác với từ MySQL.

InnoDB

Trong trường hợp của InnoDB. Điều này là do bất cứ khi nào một hàng được cập nhật trong InnoDB, chỉ mục cũng phải được cập nhật, vì chỉ mục InnoDB's phải được tuần tự, vì vậy nó phải tìm ra nút trang nào của chỉ mục mà nó được cho là được chèn vào và chèn vào đó. Đôi khi trang cụ thể đó có thể đầy, do đó, phải chia trang, lãng phí cả không gian và tăng thời gian. Điều này xảy ra bất kể cột nào bạn lập chỉ mục vì InnoDB sử dụng chỉ mục nhóm, nơi chỉ mục lưu trữ dữ liệu của toàn bộ hàng.

MyISAM

Trong trường hợp của MyISAM, nó không có vấn đề này. MyISAM thực sự chỉ sử dụng chỉ mục 1 cột, mặc dù bạn có thể đặt nhiều đơn vị trên nhiều cột. Ngoài ra MyISAM's chỉ mục không được lưu trữ tuần tự để cập nhật rất nhanh. Tương tự như vậy chèn nhanh chóng là tốt, như MyISAM chỉ cần chèn nó ở cuối hàng.

Kết luận

Vì vậy, liên quan đến câu hỏi của bạn, bạn nên xem xét thiết kế giản đồ của bạn thay vì lo lắng về việc liệu truy vấn sẽ sử dụng các chỉ số. Nếu bạn đang cập nhật chủ yếu trên một bảng, tôi khuyên bạn không nên sử dụng InnoDB trừ khi bạn cần khóa cấp hàng, đồng thời cao và giao dịch. Nếu không, MyISAM sẽ tốt hơn nhiều cho các tác vụ cập nhật. Và không nếu bạn đang sử dụng các chỉ số InnoDB không thực sự trợ giúp với việc cập nhật, đặc biệt nếu bảng rất lớn.

+0

Nếu không sử dụng các giao dịch, làm cách nào bạn xử lý dữ liệu bị hỏng trong các bảng MyISAM, nếu, ví dụ, máy chủ bị treo trong khi cập nhật? Điều này có thể quan trọng đối với một bảng nơi cập nhật là hành động chính. – Mike

+0

bạn có thể sử dụng 'CHECK TABLE tablename' và' REPAIR TABLE tablename' hoặc 'myisamchk'. Thông thường đây không phải là vấn đề khác ngoài thời gian bị mất sau một vụ tai nạn. Ngược lại, các chỉ mục InnoDB dễ bị phân mảnh và không thể sửa được bằng cách sử dụng 'ALTER TABLE innodbtable ENGINE = InnoDB' giống như các công cụ lưu trữ khác. Vì vậy, nó thực sự phụ thuộc vào hoàn cảnh của bạn. –

+0

Nếu cập nhật xảy ra khi xảy ra sự cố, có phải là tính toàn vẹn dữ liệu có thể bị xâm nhập với bảng MyISAM không - tùy thuộc vào việc cập nhật, có thể rất khó để biết bản ghi nào đã được cập nhật và ? Đối với phân mảnh chỉ mục, [docs state] (http://dev.mysql.com/doc/refman/5.5/en/innodb-file-defragmenting.html) rằng nó * có thể * được sửa với 'ALTER TABLE tbl_name ENGINE = INNODB'. Tui bỏ lỡ điều gì vậy? Dù sao, tôi đang đi ra ngoài chủ đề ở đây, và tôi đồng ý rằng nó phụ thuộc vào tình hình. Nhưng tính toàn vẹn dữ liệu là một cân nhắc quan trọng. – Mike

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