21

Tôi có bảng lớn với 2 cột: Id và Title. Id là bigint và tôi tự do chọn loại cột Tiêu đề: varchar, char, text, bất cứ điều gì. Tiêu đề cột chứa các chuỗi văn bản ngẫu nhiên như "abcdefg", "q", "allyourbasebelongtous" với tối đa 255 ký tự.Cách nhanh nhất để tìm chuỗi bằng chuỗi con trong SQL?

Nhiệm vụ của tôi là nhận chuỗi bằng chuỗi con đã cho. Substrings cũng có độ dài ngẫu nhiên và có thể bắt đầu, giữa hoặc cuối chuỗi. Cách rõ ràng nhất để thực hiện:

SELECT * FROM t LIKE '%abc%' 

Tôi không quan tâm đến INSERT, tôi chỉ cần chọn nhanh. Tôi có thể làm gì để thực hiện tìm kiếm nhanh nhất có thể?

Tôi sử dụng MS SQL Server 2008 R2, tìm kiếm toàn văn bản sẽ vô ích, theo như tôi thấy.

+11

Chào mừng bạn đến với thế giới tuyệt vời của hiệu suất cơ sở dữ liệu cực kỳ nghèo :-) – paxdiablo

+8

Tại sao tìm kiếm toàn văn bản sẽ vô ích? –

+0

nền có thể là mã thông báo không? Nếu bạn có thể phân tách các từ theo dấu cách, dấu phẩy hoặc dấu gạch nối, tôi có một ý tưởng. Cho tôi biết. – sgtz

Trả lời

8

Nếu bạn muốn sử dụng ít dung lượng hơn câu trả lời của Randy và có sự lặp lại đáng kể trong dữ liệu của bạn, bạn có thể tạo cấu trúc dữ liệu cây N-Ary trong đó mỗi cạnh là ký tự tiếp theo và treo từng chuỗi và chuỗi con cuối trong dữ liệu của bạn trên đó.

Bạn đánh số các nút theo thứ tự độ sâu đầu tiên. Sau đó, bạn có thể tạo một bảng có tối đa 255 hàng cho mỗi bản ghi của bạn, với Id bản ghi của bạn và id nút trong cây của bạn khớp với chuỗi hoặc chuỗi con theo sau. Sau đó, khi bạn thực hiện tìm kiếm, bạn tìm thấy id nút đại diện cho chuỗi bạn đang tìm kiếm (và tất cả các phần tử cuối) và thực hiện tìm kiếm theo phạm vi.

+0

Cảm ơn, tôi không thể thử giải pháp của bạn và Randy ngay bây giờ, nhưng tôi sẽ thử ASAP. – msergey

4

Có vẻ như bạn đã loại trừ tất cả các lựa chọn thay thế tốt.

Bạn đã biết rằng truy vấn của bạn

SELECT * FROM t WHERE TITLE LIKE '%abc%' 

sẽ không sử dụng một chỉ số, nó sẽ làm một bảng đầy đủ quét tất cả các thời gian.

Nếu bạn đã chắc chắn rằng chuỗi đã ở bắt đầu của lĩnh vực này, bạn có thể làm

SELECT * FROM t WHERE TITLE LIKE 'abc%' 

mà sẽ sử dụng một chỉ mục trên tiêu đề.

Bạn có chắc chắn tìm kiếm văn bản đầy đủ sẽ không giúp bạn ở đây?

Tùy thuộc vào yêu cầu kinh doanh của bạn, tôi đã đôi khi được dùng logic sau đây:

  • Làm một "bắt đầu với" truy vấn (LIKE 'abc%') đầu tiên, mà sẽ sử dụng một chỉ mục.
  • Tùy thuộc vào nếu có hàng được trả về (hoặc có bao nhiêu), có điều kiện chuyển sang tìm kiếm "khó" mà sẽ làm đầy đủ quá trình quét (LIKE '%abc%')

Phụ thuộc vào những gì bạn cần, tất nhiên, nhưng Tôi đã sử dụng điều này trong các tình huống mà tôi có thể hiển thị các kết quả dễ nhất và phổ biến nhất trước tiên, và chỉ chuyển sang truy vấn khó khăn hơn khi cần thiết.

+0

Cho chuỗi con có nhiều khả năng nhất ở giữa Tiêu đề, nhưng tôi sẽ cố gắng đo lường hiệu suất theo cách tiếp cận của bạn. – msergey

+0

Hoặc Quét chỉ mục nhóm. Có lẽ không có sự khác biệt lớn. – JeffO

+0

@ Jeff - Đó chỉ là ngữ nghĩa. Quét chỉ mục cụm chỉ đơn giản là "quét toàn bộ bảng" trên một bảng có chỉ số nhóm (hầu hết các bảng sẽ được sao chép). Dù bằng cách nào, nó cũng phải đọc mọi bản ghi. – BradC

13

nếu bạn không quan tâm đến dung lượng lưu trữ, thì bạn có thể tạo một bảng khác với các mục Tiêu đề một phần, bắt đầu bằng mỗi chuỗi con (tối đa 255 mục cho mỗi tiêu đề bình thường).

theo cách này, bạn có thể lập chỉ mục các chất nền này và chỉ khớp với đầu chuỗi, nên cải thiện đáng kể hiệu suất.

+1

làm cho bảng đó trở thành một chỉ mục không duy nhất được nhóm ... đó có thể là tốt như bạn sẽ nhận được với SQL thô. – sgtz

3

Bạn có thể thêm cột được tính toán khác trên bảng: titleLength as len (title) PERSISTED. Điều này sẽ lưu trữ độ dài của cột "tiêu đề". Tạo chỉ mục về điều này.

Ngoài ra, hãy thêm một cột được tính khác có tên là: ReverseTitle as Reverse (title) PERSISTED.

Bây giờ, khi ai đó tìm kiếm từ khóa, hãy kiểm tra xem độ dài của từ khóa có giống với titlelength hay không. Nếu có, hãy thực hiện tìm kiếm "=". Nếu độ dài của từ khóa nhỏ hơn độ dài của tiêu đềLength, sau đó thực hiện LIKE. Nhưng trước tiên hãy làm một tiêu đề LIKE 'abc%', sau đó thực hiện một reverseTitle LIKE 'cba%'. Tương tự như cách tiếp cận của Brad - nghĩa là bạn thực hiện truy vấn khó tiếp theo nếu cần.

Ngoài ra, nếu các quy tắc 80-20 áp dụng cho từ khóa/dữ liệu của bạn (ví dụ: nếu hầu hết các tìm kiếm là một số ít từ khóa), thì bạn cũng có thể xem xét thực hiện một số loại bộ nhớ đệm. Ví dụ: giả sử bạn thấy rằng nhiều người dùng tìm kiếm từ khóa "abc" và tìm kiếm từ khóa này trả về các bản ghi có id 20, 22, 24, 25 - bạn có thể lưu trữ bảng này trong một bảng riêng và đã lập chỉ mục này. Và bây giờ khi ai đó tìm kiếm một từ khóa mới, trước tiên hãy tìm trong bảng "bộ nhớ cache" này để xem tìm kiếm đã được thực hiện bởi người dùng trước đó chưa. Nếu vậy, không cần phải nhìn lại trong bảng chính. Chỉ cần trả lại kết quả từ bảng "bộ nhớ cache".

Bạn cũng có thể kết hợp ở trên với Tìm kiếm văn bản SQL Server. (giả sử bạn có lý do hợp lệ để không sử dụng nó). Nhưng bạn vẫn có thể sử dụng tìm kiếm văn bản đầu tiên để rút gọn tập kết quả. và sau đó chạy một truy vấn SQL đối với bảng của bạn để có được kết quả chính xác bằng cách sử dụng các Id được trả về bởi Tìm kiếm TExt như một tham số cùng với từ khóa của bạn.

Tất cả điều này rõ ràng là giả sử bạn phải sử dụng SQL. Nếu không, bạn có thể khám phá một cái gì đó như Apache Solr.

0

Tạo chế độ xem chỉ mục có tính năng mới trong sql tạo chỉ mục trên cột mà bạn cần tìm kiếm và sử dụng chế độ xem đó sau khi tìm kiếm sẽ cho kết quả nhanh hơn.

0
  1. Sử dụng ASCII charset với clustered index cột char. Bộ ký tự ảnh hưởng đến hiệu suất tìm kiếm do kích thước dữ liệu trên cả ram và đĩa. Nút cổ chai thường là I/O.
  2. Cột của bạn dài 255 ký tự để bạn có thể sử dụng chỉ mục bình thường trên trường char của bạn thay vì văn bản đầy đủ, nhanh hơn. Không chọn các cột không cần thiết trong câu lệnh chọn của bạn.
  3. Cuối cùng, thêm RAM vào máy chủ và tăng kích thước bộ nhớ cache .
+0

Tôi tìm thấy phương pháp cây N-Ary trong câu trả lời vui nhộn khác. –

+2

Tại sao nó vui nhộn? –

0

Làm một việc, sử dụng khóa chính trên cột cụ thể & lập chỉ mục ở dạng cụm.

Sau đó tìm kiếm sử dụng bất kỳ phương pháp (thẻ hoang dã hoặc = hoặc bất kỳ), nó sẽ tìm kiếm tối ưu vì bảng là đã có trong hình thức cụm, vì vậy nó biết nơi ông có thể tìm thấy (vì cột là đã có trong hình thức sắp xếp)

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