Điều gì làm cho một câu lệnh SQL có thể mở rộng được?


252

Theo định nghĩa (ít nhất là từ những gì tôi đã thấy) có thể hiểu được có nghĩa là một truy vấn có khả năng có công cụ truy vấn tối ưu hóa kế hoạch thực hiện mà truy vấn sử dụng. Tôi đã cố gắng tìm kiếm các câu trả lời, nhưng dường như không có nhiều vấn đề. Vì vậy, câu hỏi là, cái gì không hoặc không làm cho một truy vấn SQL có thể mở rộng được? Bất kỳ tài liệu sẽ được đánh giá rất cao.

Để tham khảo: SARGable


58
+1 cho "sargable". Đó là từ của tôi trong ngày hôm nay. :-p
BFree

1
Tôi cũng có thể thêm vào câu trả lời của Adam, rằng hàng núi thông tin trong hầu hết các trường hợp cực kỳ đặc biệt đối với mỗi công cụ DB.
Hoagie

30
SARG = Tìm kiếm ARGument. Điều thú vị là: "SARG" trong tiếng Đức có nghĩa là "Quan tài", vì vậy tôi luôn phải mỉm cười khi mọi người nói về SARGABLE - có thể được đặt trong quan tài không? :-)
marc_s

khả năng phụ thuộc vào môi trường của bạn. Tài liệu của MySQL được ghi lại ở đây: dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html
Frank Farmer

Có các trường văn bản miễn phí thay vì "bảng tra cứu" cũng đi ngược lại tinh thần làm cho một truy vấn có thể sargable. Người dùng viết sai chính tả khi nhập văn bản tự do (ví dụ tên thị trấn), trong khi bảng tra cứu buộc người dùng chọn một mục chính tả chính xác. Rất đáng để gặp thêm rắc rối nhỏ, bởi vì điều này có thể được lập chỉ mục chính xác thay vì sử dụng THÍCH '% ...%' trong vị ngữ.
Kỹ sư đảo ngược

Câu trả lời:


256

Điều phổ biến nhất sẽ làm cho một truy vấn không thể thực hiện được là bao gồm một trường bên trong một hàm trong mệnh đề where:

SELECT ... FROM ...
WHERE Year(myDate) = 2008

Trình tối ưu hóa SQL không thể sử dụng một chỉ mục trên myDate, ngay cả khi có tồn tại. Nó thực sự sẽ phải đánh giá chức năng này cho mỗi hàng của bảng. Tốt hơn nhiều để sử dụng:

WHERE myDate >= '01-01-2008' AND myDate < '01-01-2009'

Một số ví dụ khác:

Bad: Select ... WHERE isNull(FullName,'Ed Jones') = 'Ed Jones'
Fixed: Select ... WHERE ((FullName = 'Ed Jones') OR (FullName IS NULL))

Bad: Select ... WHERE SUBSTRING(DealerName,4) = 'Ford'
Fixed: Select ... WHERE DealerName Like 'Ford%'

Bad: Select ... WHERE DateDiff(mm,OrderDate,GetDate()) >= 30
Fixed: Select ... WHERE OrderDate < DateAdd(mm,-30,GetDate()) 

7
Sẽ bao gồm một chức năng bên trong GROUP BYgây ra một truy vấn trở thành không thể sargable?
Mike Bailey

1
Một số công cụ cơ sở dữ liệu (Oracle, PostgreSQL) hỗ trợ các chỉ mục về biểu thức, không biết?
Craig

3
Một phiên bản tốt hơn của sẽ WHERE ((FullName = 'Ed Jones') OR (FullName IS NULL))được SELECT... FROM ... WHERE FullName = 'Ed Jones' UNION SELECT...FROM...WHERE FullName IS NULL? Tôi đã từng được một người tối ưu hóa nói rằng sử dụng OR trong mệnh đề where có thể bỏ các truy vấn không ..?
Cao nguyên Grifter

2
@HighPlainsSau khi bạn nên sử dụng UNION ALL cho truy vấn đó - union có một sự khác biệt ngầm định, khiến cho một truy vấn đắt hơn nhiều so với khi bạn phải loại bỏ các bộ dữ liệu loại trừ lẫn nhau
Devin Lamothe vào

1
@BradC Trong MSSQL 2016, không có sự khác biệt về kế hoạch thực hiện giữa Select ... WHERE isNull(FullName,'Ed Jones') = 'Ed Jones'Select ... WHERE ((FullName = 'Ed Jones') OR (FullName IS NULL)). Cả hai đều sử dụng chỉ mục trên FullName và thực hiện tìm kiếm chỉ mục.
CEGRD

79

Đừng làm điều này:

WHERE Field LIKE '%blah%'

Điều đó gây ra quét bảng / chỉ mục, bởi vì giá trị THÍCH bắt đầu bằng ký tự đại diện.

Đừng làm điều này:

WHERE FUNCTION(Field) = 'BLAH'

Điều đó gây ra quét bảng / chỉ mục.

Máy chủ cơ sở dữ liệu sẽ phải đánh giá FUNCTION () theo từng hàng trong bảng và sau đó so sánh nó với 'BLAH'.

Nếu có thể, hãy làm ngược lại:

WHERE Field = INVERSE_FUNCTION('BLAH')

Điều này sẽ chạy INVERSE_FUNCTION () đối với tham số một lần và vẫn sẽ cho phép sử dụng chỉ mục.


5
Đề xuất của bạn với việc lật hàm sẽ thực sự chỉ hoạt động khi dữ liệu khứ hồi của hàm (có nghĩa là f (f (n)) = n).
Adam Robinson

5
Thật. Tôi đã xem xét việc thêm INVERSE_FUNCTION nhưng không muốn gây nhầm lẫn. Tôi sẽ thay đổi nó.
bãi biển

9

Trong câu trả lời này, tôi giả sử cơ sở dữ liệu có đủ các chỉ mục. Có đủ câu hỏi về chủ đề này .

Rất nhiều lần khả năng của một truy vấn được xác định bởi điểm tới hạn của các chỉ mục liên quan. Điểm tới hạn xác định sự khác biệt giữa tìm kiếm và quét một chỉ mục trong khi nối một bảng hoặc kết quả được đặt trên một bảng khác. Một tìm kiếm tất nhiên nhanh hơn nhiều so với quét toàn bộ bảng, nhưng khi bạn phải tìm kiếm nhiều hàng, việc quét có thể có ý nghĩa hơn.

Vì vậy, trong số những điều khác, một câu lệnh SQL có thể dễ hiểu hơn khi trình tối ưu hóa dự kiến ​​số lượng hàng kết quả của một bảng sẽ nhỏ hơn điểm tới hạn của một chỉ mục có thể trên bảng tiếp theo.

Bạn có thể tìm thấy một bài viết chi tiết và ví dụ ở đây .


4

Đối với một hoạt động được coi là có thể mở rộng, nó không đủ để chỉ có thể sử dụng một chỉ mục hiện có. Trong ví dụ trên, việc thêm một lệnh gọi hàm vào một cột được lập chỉ mục trong mệnh đề where, rất có thể vẫn sẽ tận dụng một số lợi thế của chỉ mục được xác định. Nó sẽ "quét" aka lấy tất cả các giá trị từ cột (chỉ mục) đó và sau đó loại bỏ những giá trị không khớp với giá trị bộ lọc được cung cấp. Nó vẫn không đủ hiệu quả cho các bảng có số lượng hàng cao. Điều thực sự định nghĩa khả năng sargability là khả năng truy vấn để duyệt qua chỉ mục cây b bằng cách sử dụng phương pháp tìm kiếm nhị phân dựa trên loại bỏ nửa tập cho mảng các mục được sắp xếp. Trong SQL, nó sẽ được hiển thị trên kế hoạch thực hiện dưới dạng "tìm kiếm chỉ mục".

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.