THÍCH sử dụng chỉ mục, CHARINDEX không?


22

Câu hỏi này liên quan đến câu hỏi cũ của tôi . Truy vấn dưới đây mất 10 đến 15 giây để thực hiện:

SELECT [customer].[Customer name],[customer].[Sl_No],[customer].[Id]
FROM [company].dbo.[customer]
WHERE (Charindex('123456789',CAST([company].dbo.[customer].[Phone no] AS VARCHAR(MAX)))>0) 

Trong một số bài viết tôi thấy rằng sử dụng CASTCHARINDEXsẽ không được hưởng lợi từ việc lập chỉ mục. Cũng có một số bài viết nói rằng việc sử dụng LIKE '%abc%'sẽ không được hưởng lợi từ việc lập chỉ mục trong khi LIKE 'abc%'sẽ:

http://bytes.com/topic/sql-server/answers/81467-USE-charindex-vs-like-where /programming/803783/sql-server-index-any-improference-for -like-truy vấn http://www.sqlservercentral.com/Forums/Topic186262-8-1.aspx#bm186568

Trong trường hợp của tôi, tôi có thể viết lại truy vấn dưới dạng:

SELECT [customer].[Customer name],[customer].[Sl_No],[customer].[Id]
FROM [company].dbo.[customer]
WHERE [company].dbo.[customer].[Phone no]  LIKE '%123456789%'

Truy vấn này cho cùng một đầu ra như trước đó. Tôi đã tạo một chỉ mục không bao gồm cho cột Phone no. Khi tôi thực hiện truy vấn này, nó sẽ chạy chỉ trong 1 giây . Đây là một thay đổi rất lớn so với 14 giây trước đây.

Làm thế nào để LIKE '%123456789%'hưởng lợi từ việc lập chỉ mục?

Tại sao các bài viết được liệt kê nói rằng nó sẽ không cải thiện hiệu suất?

Tôi đã thử viết lại truy vấn để sử dụng CHARINDEX, nhưng hiệu suất vẫn chậm. Tại sao CHARINDEXkhông được hưởng lợi từ việc lập chỉ mục khi nó xuất hiện LIKEtruy vấn?

Truy vấn bằng cách sử dụng CHARINDEX:

SELECT [customer].[Customer name],[customer].[Sl_No],[customer].[Id]
 FROM [Company].dbo.[customer]
 WHERE ( Charindex('9000413237',[Company].dbo.[customer].[Phone no])>0 ) 

Kế hoạch thực hiện:

nhập mô tả hình ảnh ở đây

Truy vấn bằng cách sử dụng LIKE:

SELECT [customer].[Customer name],[customer].[Sl_No],[customer].[Id]
 FROM [Company].dbo.[customer]
 WHERE[Company].dbo.[customer].[Phone no] LIKE '%9000413237%'

Kế hoạch thực hiện:

Kế hoạch truy vấn THÍCH

Câu trả lời:


28

Làm thế nào để THÍCH '% 123456789%' được lập chỉ mục?

Chỉ một chút. Bộ xử lý truy vấn có thể quét toàn bộ chỉ mục không bao gồm tìm kiếm các kết quả khớp thay vì toàn bộ bảng (chỉ mục được nhóm). Các chỉ mục không bao gồm thường nhỏ hơn bảng mà chúng được xây dựng, do đó việc quét chỉ mục không bao gồm có thể nhanh hơn.

Nhược điểm, là bất kỳ cột nào cần thiết cho truy vấn không được bao gồm trong định nghĩa chỉ mục không bao gồm phải được tra cứu trong bảng cơ sở, trên mỗi hàng.

Trình tối ưu hóa đưa ra quyết định giữa việc quét bảng (chỉ mục được nhóm) và quét chỉ mục không bao gồm với tra cứu, dựa trên ước tính chi phí. Các chi phí ước tính phụ thuộc rất nhiều vào số lượng hàng mà trình tối ưu hóa mong đợiLIKE hoặc CHARINDEXvị ngữ của bạn sẽ chọn.

Tại sao các bài viết được liệt kê nói rằng nó sẽ không cải thiện hiệu suất?

Đối với một LIKEđiều kiện không bắt đầu bằng ký tự đại diện, SQL Server có thể thực hiện quét một phần chỉ mục thay vì quét toàn bộ. Ví dụ, LIKE 'A%có thể được đánh giá chính xác bằng cách chỉ kiểm tra các bản ghi chỉ mục >= 'A'< 'B'(các giá trị biên chính xác phụ thuộc vào đối chiếu).

Loại truy vấn này có thể sử dụng khả năng tìm kiếm của các chỉ mục b-cây: chúng ta có thể đi thẳng đến bản ghi đầu tiên >= 'A'bằng cách sử dụng cây b, sau đó quét về phía trước theo thứ tự khóa chỉ mục cho đến khi chúng ta đạt được một bản ghi không < 'B'kiểm tra. Vì chúng ta chỉ cần áp dụng LIKEthử nghiệm cho số lượng hàng nhỏ hơn, nên hiệu suất thường tốt hơn.

Ngược lại, LIKE '%Akhông thể biến thành quét một phần vì chúng ta không biết bắt đầu hay kết thúc ở đâu; bất kỳ bản ghi nào cũng có thể kết thúc 'A', vì vậy chúng tôi không thể cải thiện việc quét toàn bộ chỉ mục và kiểm tra từng hàng riêng lẻ.

Tôi đã thử viết lại truy vấn để sử dụng CHARINDEX, nhưng hiệu suất vẫn chậm. Tại sao CHARINDEXkhông được hưởng lợi từ việc lập chỉ mục khi nó xuất hiện truy vấn THÍCH?

Trình tối ưu hóa truy vấn có cùng lựa chọn giữa quét bảng (chỉ mục được nhóm) và quét chỉ mục không bao gồm (có tra cứu) trong cả hai trường hợp.

Sự lựa chọn được thực hiện giữa hai dựa trên dự toán chi phí . Do đó, SQL Server có thể tạo ra một ước tính khác nhau cho hai phương thức. Đối với LIKEdạng truy vấn, ước tính có thể có thể sử dụng số liệu thống kê chuỗi đặc biệt để tạo ước tính chính xác hợp lý. Các CHARINDEX > 0hình thức tạo ra một ước tính dựa trên một dự đoán.

Các ước tính khác nhau là đủ để làm cho trình tối ưu hóa chọn Quét CHARINDEXchỉ mục theo cụm và Quét chỉ mục không làm mờ với tra cứu cho LIKE. Nếu bạn buộc CHARINDEXtruy vấn sử dụng chỉ mục không bao gồm với một gợi ý, bạn sẽ nhận được cùng một kế hoạch như đối với LIKEvà hiệu suất sẽ giống nhau:

SELECT
    [Customer name],
    [Sl_No],
    [Id]
FROM dbo.customer WITH (INDEX (f))
WHERE 
    CHARINDEX('9000413237', [Phone no]) >0;

Số lượng hàng được xử lý trong thời gian chạy sẽ giống nhau cho cả hai phương thức, chỉ là LIKEbiểu mẫu tạo ra ước tính chính xác hơn trong trường hợp này, vì vậy trình tối ưu hóa truy vấn chọn một kế hoạch tốt hơn.

Nếu bạn thấy mình cần LIKE %thing%tìm kiếm thường xuyên, bạn có thể muốn xem xét một kỹ thuật tôi đã viết trong Tìm kiếm chuỗi ký tự đại diện Trigram trong SQL Server .


16

SQL Server duy trì số liệu thống kê về chuỗi con trong các cột chuỗi dưới dạng thử có thể sử dụng được bằng LIKEtruy vấn nhưng không phải bởi CHARINDEX.

Xem phần Thống kê Tóm tắt Chuỗi để biết thêm về điều này.

Một vài lưu ý quan trọng là bất kỳ việc thoát ký tự đại diện nào cũng phải được thực hiện bằng kỹ thuật đặt dấu ngoặc vuông độc quyền thay vì ESCAPEtừ khóa và đối với các chuỗi dài hơn 80 ký tự chỉ sử dụng 40 ký tự đầu tiên và 40 ký tự cuối cùng.

WHERE ( Charindex('9000413237',[Company].dbo.[customer].[Phone no])>0 ) 

sẽ chỉ sử dụng dự đoán tiêu chuẩn cho một vị từ bất đẳng thức rằng 30% số hàng sẽ được trả về.

Các LIKEtruy vấn (trong trường hợp của bạn) có lẽ là ước tính ít hàng hơn nhiều sẽ phù hợp với vị ngữ.

Lưu ý rằng ký tự đại diện hàng đầu vẫn ngăn chặn tìm kiếm chỉ mục. Toàn bộ một chỉ mục vẫn được quét nhưng nó sử dụng một chỉ số khác hẹp hơn so với chỉ mục được nhóm. Chỉ mục hẹp hơn không bao gồm tất cả các cột được sử dụng bởi truy vấn, vì vậy kế hoạch thứ hai yêu cầu tra cứu khóa để truy xuất các cột bị thiếu.

Kế hoạch này cực kỳ khó được lựa chọn với ước tính 30%. SQL Server sẽ xem xét việc quét toàn bộ chỉ mục được nhóm và tránh nhiều lần tra cứu đó là rẻ hơn. Xem bài viết này về điểm tới hạn để biết thêm ví dụ.


tôi không rõ ràng với lời giải thích của bạn. Bạn đang nói rằng sử dụng like tốt hơn charindex?
nghiên cứu CNTT

3
@ITresearcher - Có, có khả năng, thay vì chỉ sử dụng một chiếc chăn đoán xem có bao nhiêu hàng sẽ khớp với điều kiện ( 30%) nó có thể nhìn vào LIKEmẫu được cung cấp và thống kê tóm tắt chuỗi và đưa ra ước tính chính xác hơn. Được trang bị với nó có thể chọn một kế hoạch khác và phù hợp hơn.
Martin Smith

3
... Hoặc, trong "trường hợp xấu nhất", cùng một kế hoạch.
Aaron Bertrand
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.