2009-04-29 65 views
18

Chúng tôi có một truy vấn chạy ra một bảng khá lớn mà tiếc là cần phải sử dụng LIKE '% ABC%' trên một vài trường varchar để người dùng có thể tìm kiếm trên một phần tên, vv SQL Server 2005SQL Server Index - Bất kỳ cải tiến nào cho các truy vấn LIKE?

Sẽ thêm một chỉ mục trên các trường VARCHAR giúp bất kỳ về hiệu suất truy vấn chọn khi sử dụng LIKE hoặc không nó về cơ bản bỏ qua các chỉ mục và làm một quét đầy đủ trong những trường hợp?

Bất kỳ cách nào khác có thể để cải thiện hiệu suất khi sử dụng LIKE?

Trả lời

18

Chỉ khi bạn thêm tìm kiếm toàn văn vào các cột đó và sử dụng khả năng truy vấn toàn văn của SQL Server.

Nếu không, không, chỉ mục sẽ không hữu ích.

+0

Cảm ơn, đó là điều tôi nghĩ không may. Tôi đã loại bỏ một số mệnh đề LIKE để giúp tăng tốc độ lên một chút. – schooner

2

Giống như '% ABC%' sẽ luôn thực hiện quét toàn bộ bảng. Không có cách nào xung quanh đó.

Bạn có một vài phương pháp thay thế khác. Trước hết là tìm kiếm văn bản đầy đủ, nó thực sự được thiết kế cho loại vấn đề này vì vậy tôi sẽ xem xét điều đó trước tiên. Ngoài ra, trong một số trường hợp, có thể thích hợp để chuẩn hóa dữ liệu và xử lý trước các trường mục tiêu thành các thẻ thích hợp, sau đó thêm các cụm từ tìm kiếm có thể này vào một cụm từ tìm kiếm riêng biệt cho nhiều bảng tìm kiếm. Ví dụ, nếu dữ liệu của tôi luôn bao gồm một trường có chứa mẫu 'AAA/BBB/CCC' và người dùng của tôi đang tìm kiếm trên BBB thì tôi sẽ thông báo lỗi đó khi chèn/cập nhật (và xóa khi xóa). Đây cũng sẽ là một trong những trường hợp sử dụng trình kích hoạt, thay vì mã ứng dụng, sẽ là nhiều ưu tiên hơn.

Tôi phải nhấn mạnh rằng đây không thực sự là một kỹ thuật tối ưu và chỉ nên sử dụng nếu dữ liệu phù hợp với cách tiếp cận và vì lý do nào đó bạn không muốn sử dụng tìm kiếm toàn văn (và hiệu suất cơ sở dữ liệu như quét thực sự là không thể chấp nhận được). Nó cũng có khả năng tạo ra các cơn đau đầu duy trì tiếp tục xuống dòng.

8

Cách khác duy nhất (trừ sử dụng lập chỉ mục toàn văn) bạn có thể cải thiện hiệu suất là sử dụng "LIKE ABC%" - không thêm ký tự đại diện trên cả hai đầu của cụm từ tìm kiếm của bạn - trong trường hợp đó, chỉ mục có thể hoạt động .

Nếu yêu cầu của bạn là như vậy mà bạn phải có ký tự đại diện trên cả hai đầu của thuật ngữ tìm kiếm của bạn, bạn đang trên may mắn ...

Marc

+0

Điều này chỉ làm việc cho 'LIKE ABC%', hay nó cũng hoạt động cho 'LIKE% ABC'? Ngoài ra, tôi tò mò tại sao nó hoạt động với một ký tự đại diện một mặt ... Bạn có thể giải thích về điều đó không? –

+0

@ TomPažourek: tốt - hãy tưởng tượng một cuốn sách điện thoại (nếu bạn đủ tuổi để nhớ đó là gì :-); nếu bạn đang tìm kiếm họ của ai đó ** bắt đầu bằng ** 'Smi', bạn sẽ tìm thấy' Smith' và 'Smithers' vv khá nhanh. Nhưng nếu bạn tìm kiếm ai đó có họ ** chứa ** (bất kỳ nơi nào trong tên), ví dụ: 'chuk', có danh sách được sắp xếp của các tên (đó là những gì một ** chỉ mục ** thực sự là) không thực sự giúp bạn nhiều - bạn vẫn phải cuộn qua ** tất cả các tên ** để tìm những người có chuỗi đó tên của họ –

+0

Cảm ơn. :-) Bạn có biết cấu trúc dữ liệu nào được sử dụng không? Nó là một hình thức của một trie? Điều đó có nghĩa là '% ABC' sẽ không sử dụng bất kỳ chỉ mục nào? Bạn chỉ đề cập rằng ký tự đại diện trên cả hai đầu sẽ không hoạt động. Liệu ký tự đại diện trên công việc cuối cùng phải không? –

-2

tạo thống kê về cột đó. sql srever 2005 đã tối ưu hóa tìm kiếm chuỗi để bạn có thể thích hợp hơn.

11

Bạn có khả năng có thể thấy những cải thiện hiệu suất bằng cách thêm chỉ mục (es), nó phụ thuộc rất nhiều vào các chi tiết cụ thể :)

bao nhiêu phần trăm tổng kích thước của hàng là cột xác của bạn? Bạn mong đợi bao nhiêu hàng? Bạn có cần trả về tất cả các hàng khớp với vị từ hoặc chỉ các hàng trên cùng hoặc hàng đầu n không?

Nếu bạn đang tìm kiếm các giá trị có độ chọn lọc/tính duy nhất cao (vì vậy ít hàng để trả về) và cột được xác định là một phần nhỏ của toàn bộ kích thước hàng, chỉ mục có thể khá hữu ích. Nó vẫn sẽ là một lần quét, nhưng chỉ mục của bạn sẽ phù hợp với nhiều hàng trên mỗi trang hơn so với bảng nguồn.

Dưới đây là một ví dụ trong đó tổng kích thước hàng lớn hơn nhiều so với kích thước cột để tìm kiếm trên:

create table t1 (v1 varchar(100), b1 varbinary(8000)) 
go 
--add 10k rows of filler 
insert t1 values ('abc123def', cast(replicate('a', 8000) as varbinary(8000))) 
go 10000 
--add 1 row to find 
insert t1 values ('abc456def', cast(replicate('a', 8000) as varbinary(8000))) 
go 

set statistics io on 
go 
select * from t1 where v1 like '%456%' 
--shows 10001 logical reads 

--create index that only contains the column(s) to search across 
create index t1i1 on t1(v1) 
go 
select * from t1 where v1 like '%456%' 
--or can force to 
--shows 37 logical reads 

Nếu bạn nhìn vào kế hoạch thực hiện thực tế bạn sẽ nhìn thấy động cơ quét chỉ mục và đã làm một tra cứu dấu trang trên hàng phù hợp. Hoặc bạn có thể yêu cầu trình tối ưu hóa trực tiếp sử dụng chỉ mục, nếu nó không quyết định sử dụng kế hoạch này một mình: chọn * từ t1 với (chỉ mục (t1i1)) trong đó v1 như '% 456%'

Nếu bạn có một loạt các cột để tìm kiếm chỉ trên một vài cột có tính chọn lọc cao, bạn có thể tạo nhiều chỉ mục và sử dụng phương pháp giảm. Ví dụ. trước tiên hãy xác định một tập hợp các ID (hoặc bất kỳ PK nào của bạn) từ chỉ mục có chọn lọc cao của bạn, sau đó tìm kiếm các cột ít chọn lọc của bạn hơn bằng bộ lọc chống lại tập hợp PK nhỏ đó.

Nếu bạn luôn cần phải trả lại một tập hợp lớn các hàng, bạn gần như chắc chắn sẽ tốt hơn với việc quét bảng.

Vì vậy, các tối ưu hóa có thể phụ thuộc rất nhiều vào các chi tiết cụ thể về định nghĩa bảng và tính chọn lọc dữ liệu của bạn.

HTH! -Adrian

+0

Đồng thời xem xét các chỉ mục INCLUDE nếu bạn trả lại một tập con của các cột trong một bảng rộng. –

+0

Cũng xem xét dữ liệu bạn đang truy vấn. Ví dụ: thêm Chỉ mục được lọc loại trừ các chuỗi rỗng và/hoặc rỗng và sau đó sử dụng chỉ mục đó trong truy vấn của bạn sẽ giúp hiệu suất rất nhiều. Chỉ số sẽ nhỏ hơn và sau đó ít hơn cho LIKE để quét. –

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