SQL Server: Bao gồm các chỉ mục bao gồm tất cả các cột?


9

Nhóm của chúng tôi đã kế thừa một ứng dụng và cơ sở dữ liệu liên quan. Các nhà phát triển trước đó dường như đã thực thi một quy tắc trong đó mọi chỉ mục, trên mỗi bảng, có một mệnh đề INCLUDE để luôn thêm mọi cột không phải là một phần của khóa. Các bảng này có trung bình bất cứ nơi nào từ hai đến năm chỉ mục hoặc các ràng buộc duy nhất cũng như các khóa ngoại.

Mục đích dường như là để cải thiện hiệu suất CHỌN bất kể truy vấn nào được ném vào cơ sở dữ liệu, vì quyền truy cập thông qua ORM theo mặc định (nhưng không phải luôn luôn) lấy tất cả các cột. Chúng tôi hy vọng rằng các tác dụng phụ của việc này là tăng yêu cầu lưu trữ (có thể là đáng kể) và thời gian trên không bổ sung cho CHERTN / CẬP NHẬT / XÓA.

Câu hỏi là, đây có phải là một chiến lược hợp lý? Nhóm của chúng tôi có lịch sử với SQL Server nhưng không có thành viên nào tự coi mình là chuyên gia về hành vi nội bộ của nó (mặc dù câu hỏi đã được đặt ra là nếu chiến lược này là tối ưu, liệu bây giờ nó có phải là mặc định không?). Những tác dụng phụ nào khác (sử dụng CPU / bộ nhớ / TempDB của máy chủ cơ sở dữ liệu, v.v.) chúng ta nên mong đợi, hoặc một số giả định của chúng tôi ở trên không chính xác?

Ngoài ra, ứng dụng có thể được cài đặt vào cả SQL Server tại cơ sở (phiên bản từ năm 2012), cũng như Azure SQL - chúng ta nên chuẩn bị cho bất kỳ sự khác biệt nào giữa hai hoặc tác dụng phụ bổ sung trên Azure, do kết quả của việc này tiếp cận?

Câu trả lời:


8

Tôi đã thực hiện điều này trên các chỉ mục cụ thể trước đây, để hỗ trợ các truy vấn nặng. Thực tế, những gì họ đã làm là tạo ra nhiều chỉ mục được phân cụm: khi bất kỳ chỉ mục nào được sử dụng để tìm các hàng thì không cần làm thêm việc tìm kiếm phần còn lại của dữ liệu trong chỉ mục được phân cụm thực (hoặc heap nếu không có chỉ mục được phân cụm thực sự) .

Đây có phải là một chiến lược hợp lý?

Đối với một số chỉ mục cần hỗ trợ một số mẫu truy vấn nhất định, chắc chắn là có.

Nhưng để làm điều này với tất cả các chỉ số, tôi chắc chắn sẽ nói không.

Sẽ rất lãng phí không gian để làm ở những nơi không thực sự cần thiết và sẽ làm chậm đáng kể việc chèn / cập nhật. Nó có thể làm chậm nhiều truy vấn đọc vì nó cũng giúp, vì mỗi trang chỉ mục chứa ít bản ghi hơn nên mọi truy vấn cần tham chiếu một đoạn của chỉ mục để lọc nhưng không sử dụng tất cả các cột khác sẽ phải truy cập vào nhiều trang hơn. Điều này sẽ làm cho cơ sở dữ liệu của bạn ngốn nhiều bộ nhớ hơn: những trang đó sẽ cần được tải vào nhóm bộ đệm, có khả năng đẩy các trang hữu ích khác nếu bộ nhớ thấp. Nếu nén được sử dụng trên các chỉ mục đó để cố gắng giảm thiểu ảnh hưởng đến các yêu cầu lưu trữ và bộ nhớ, thì nó sẽ đẩy thêm tải cho CPU thay thế.

vì quyền truy cập thông qua ORM mà theo mặc định (nhưng không phải luôn luôn) truy xuất tất cả các cột

Đây là một mẫu phổ biến với việc sử dụng ORM (hoặc ORM ngây thơ) được tối ưu hóa kém và trong các trường hợp này, tôi đã thấy trình cố vấn chỉ mục của SQL Server (và các công cụ bên thứ 3 tương tự) đề xuất các chỉ mục có nhiều INCLUDEcột d, vì vậy tôi sẽ đồng ý với đề nghị rằng đây là lý do tại sao các chỉ mục đã được tạo ra theo cách này.

Nhưng trong khi nó có thể làm cho tất cả các truy vấn như vậy nhanh hơn một chút và một số trong số chúng nhanh hơn đáng kể, tôi nghi ngờ rằng trong nhiều trường hợp, bất kỳ lợi ích nào cũng nhỏ đến mức không xứng đáng với dung lượng bộ nhớ bổ sung theo yêu cầu của bộ làm việc chung của bạn, không gian trên đĩa và IO giữa đĩa và bộ nhớ.

Ngoài ra, hãy nhớ rằng ORM có thể không chọn tất cả các cột của tất cả các bảng mà truy vấn chạm, do đó, lợi ích chỉ có thể giữ cho mục tiêu chính của yêu cầu hiện tại và các chỉ mục lớn hơn có thể xử phạt truy vấn khi các đối tượng khác được sử dụng để lọc nhưng không trả lại dữ liệu ( SELECT * FROM table1 WHERE id IN (SELECT someID FROM table2 WHERE someColumn='DesiredValue')có lẽ).

Một xem xét khác cho không gian thừa được sử dụng, đặc biệt nếu dữ liệu lớn, là nó sẽ có tác động đến chiến lược sao lưu của bạn: chi phí lưu trữ và chuyển giao cho các bản sao lưu đó, thời gian khôi phục tiềm năng, v.v.

chúng ta nên chuẩn bị cho bất kỳ sự khác biệt nào giữa hai [tại chỗ & AzureQuery]

Nói chung, tôi nghĩ rằng các cân nhắc ở đây sẽ giống nhau trong từng trường hợp, mặc dù mọi chi phí bộ nhớ / IO vượt quá áp đặt bởi các chỉ mục lớn có thể hiển thị trực tiếp hơn trong Azure nơi bạn có thể điều chỉnh tầng dịch vụ và do đó chi phí cơ sở hạ tầng dễ dàng hơn thay vì có một bộ tài nguyên phần cứng tương đối cố định. Nếu sử dụng các mức tiêu chuẩn / cao cấp thay vì định giá dựa trên vcore thì bạn sẽ bị ảnh hưởng nhiều hơn bởi chi phí IO trong tiêu chuẩn vì phí bảo hiểm bao gồm nhiều IO hơn trên mỗi DTU. Nếu bạn đang sử dụng sao lưu đa vùng hoặc dự phòng hoặc các tính năng không cục bộ khác trong Azure thì có thể có chi phí băng thông liên quan đến không gian thêm được thực hiện bởi các chỉ mục rộng bất thường.


Chúng tôi đã đi trước và làm điều này loại bỏ. Một tác dụng phụ là trên các bảng nhất định, SELECTkhông chỉ định ORDER BYbắt đầu trả về các hàng giống như trước nhưng với một thứ tự tùy ý khác.
T2PS

Điều đó không bất ngờ. Thứ tự của các kết quả mà không có 'ORDER BY' là theo định nghĩa không xác định và có thể thay đổi bất cứ khi nào trình hoạch định truy vấn quyết định thực hiện một cách tiếp cận khác, điều này có thể làm do kết quả của thay đổi chỉ mục hoặc thay đổi trong mẫu dữ liệu của bạn khi nó phát triển. Các yếu tố khác có thể làm cho đơn đặt hàng như vậy thay đổi vào một ngày sau đó ngay cả khi không có thay đổi này. Nếu bạn dựa vào thứ tự đầu ra của câu lệnh, thậm chí là bề ngoài, thì bạn cần bao gồm một 'ĐẶT HÀNG B' NG 'để đảm bảo nó.
David Spillett

Ồ, chắc chắn rồi. Nhận xét trước đó có ý nghĩa nhiều hơn như một lời nhắc nhở cho bất cứ ai tìm thấy câu trả lời này sau đó.
T2PS

5

Câu hỏi đặt ra là đây có phải là một chiến lược hợp lý không? .... (mặc dù câu hỏi đã được đặt ra rằng nếu chiến lược này là tối ưu, liệu bây giờ nó có được mặc định không?)

Trong hầu hết các trường hợp, đây không phải là một chiến lược hợp lý. Lý do là, trong các cơ sở dữ liệu OLTP nói chung, các hàng được trả về cho người dùng cuối sẽ không phải là toàn bộ. (Sự khái quát)

Câu hỏi bạn nên tự hỏi mình là, nếu bạn đang tìm kiếm trên các cột chính, có bao nhiêu hàng sẽ được trả về bởi hoạt động tìm kiếm đó? Và lặp lại điều đó cho các truy vấn tìm kiếm trên cột đó.

Hãy xem xét bảng sau, trả về toàn bộ nhiều cột, where SelectiveIDField= ...

select columnA,columnC, ... columnZ
FROM dbo.BigTable
Where SelectiveIDField= '225122141';

Nếu chỉ có một hàng sẽ được trả về bởi tìm kiếm trên selectiveIDField, việc tìm kiếm khóa bổ sung có phải là một điều xấu không? (đoán bạn đã phân cụm các chỉ mục ở đây, nếu không thì tra cứu RID)

Nó sẽ chỉ thực hiện thêm một tra cứu khóa, thêm một lần thực hiện + toán tử nối. Ngay cả khi nó là 10 hoặc thậm chí 100, nó sẽ có ảnh hưởng rất lớn? Điều này cũng phụ thuộc vào mức độ truy vấn của bạn được thực hiện và thời gian thực hiện quan trọng như thế nào.

Trong trường hợp nó không đáng kể, chỉ cần tạo chỉ mục trên SelectiveIDFieldvà gọi nó là một ngày, nó không đáng để đạt được mức tăng đọc so với tổn thất ghi.

Vì vậy, trong ngắn hạn, việc tạo các chỉ mục trên toàn bộ bảng theo tôi không nên là một cách tiếp cận mặc định trừ khi bạn thực sự thấy một vấn đề với một truy vấn và có thể cải thiện nó một cách quyết liệt bằng cách thêm toàn bộ chỉ mục bao trùm.

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.