Cách tiếp cận tốt hơn cho việc THÍCH THÍCH HOẶC THÍCH, HOẶC THÍCH, HOẶC THÍCH, HOẶC THÍCH


10

Trong câu hỏi này , anh ta có cùng một vấn đề như tôi. Tôi cần một cái gì đó như:

select * from blablabla 
where product 
like '%rock%' or
like '%paper%' or
like '%scisor%' or
like '%car%' or
like '%pasta%' 

Điều này thật tệ và nó không sử dụng các chỉ mục .. Trong trường hợp này, đây thực sự là cách duy nhất để làm điều này (để chọn nhiều từ trong một chuỗi), hay tôi nên sử dụng FULLTEXT?

Theo tôi hiểu, với fulltext, tôi có thể chọn nhiều từ trong một chuỗi.

Câu hỏi này cũng nói về Toàn văn


3
Kiểu dữ liệu của cột sản phẩm là gì? Trung bình có bao nhiêu nhân vật?
Joe Obbish

Câu trả lời:


17

Các chỉ mục toàn văn thường không phải là một viên đạn ma thuật và yêu cầu bảo trì bổ sung, dung lượng ổ đĩa và các thay đổi khá xâm phạm đối với các mẫu truy vấn.

Trừ khi bạn thực sự cần lập chỉ mục các tài liệu lớn (nghĩ rằng các nội dung email, PDF, tài liệu Word, v.v.), chúng sẽ quá mức cần thiết (và nếu chúng ta trung thực, tôi sẽ loại bỏ hoàn toàn quy trình đó khỏi SQL Server và sử dụng Elaticsearch hoặc một cái gì đó tương tự).

Đối với các trường hợp sử dụng nhỏ hơn, các cột được tính toán thường là cách tiếp cận tốt hơn.

Đây là một thiết lập demo nhanh:

use tempdb

CREATE TABLE #fulltextindexesarestupid (Id INT PRIMARY KEY CLUSTERED, StopAbusingFeatures VARCHAR(100))

INSERT #fulltextindexesarestupid (Id)
SELECT TOP 1000000 ROW_NUMBER() OVER (ORDER BY (@@ROWCOUNT))
FROM sys.messages AS m
CROSS JOIN sys.messages AS m2

UPDATE #fulltextindexesarestupid
SET StopAbusingFeatures = CASE WHEN Id % 15 = 0 THEN 'Bad'
                               WHEN Id % 3 = 0 THEN 'Idea'
                               WHEN Id % 5 = 0 THEN 'Jeans'
                               END


ALTER TABLE #fulltextindexesarestupid 
ADD LessBad AS CONVERT(BIT, CASE WHEN StopAbusingFeatures LIKE '%Bad%' THEN 1
                    WHEN StopAbusingFeatures LIKE '%Idea%' THEN 1
                    ELSE 0 END)

CREATE UNIQUE NONCLUSTERED INDEX ix_whatever ON #fulltextindexesarestupid (LessBad, Id)

Truy vấn dựa trên ngay cả một cột không kiên trì cung cấp cho chúng tôi một kế hoạch "sử dụng chỉ mục" và mọi thứ :)

SELECT COUNT(*)
FROM #fulltextindexesarestupid AS f
WHERE LessBad = 1

QUẢ HẠCH


-3

Câu trả lời của sp_BlitzErik đạt được rất nhiều điểm hay, nhưng tôi không nghĩ đó là lý do tại sao bạn không nên sử dụng Tìm kiếm toàn văn. Tìm kiếm toàn văn không có ở đó để làm những gì bạn nghĩ nó làm. Nó không ở đó để tìm kiếm nhiều lĩnh vực. Nó ở đó để vector hóa nội dung từ và sử dụng từ điển, stubbing, lexers, gazetteers, loại bỏ từ dừng, và một loạt các thủ thuật khác không áp dụng. Hoặc, chưa được hiển thị để áp dụng.

Tôi cũng không đồng ý với giải pháp này, mặc dù tôi không chắc làm thế nào để làm điều này tốt hơn trong SQL Server. Hãy tạo lại dữ liệu của anh ấy cho PostgreSQL - nó cũng dễ tạo ra hơn trong PostgreQuery.

CREATE TABLE fulltextindexesarestupid
AS
  SELECT
    id,
    CASE WHEN Id % 15 = 0 THEN 'Bad'
      WHEN Id % 3 = 0 THEN 'Idea'
      WHEN Id % 5 = 0 THEN 'Jeans'
    END AS StopAbusingFeatures
  FROM generate_series(1,1000000) AS id;

Bây giờ những gì bạn muốn là một loại enum,

CREATE TYPE foo AS ENUM ('Bad', 'Idea', 'Jeans');

ALTER TABLE fulltextindexesarestupid
  ALTER StopAbusingFeatures
  SET DATA TYPE foo
  USING StopAbusingFeatures::foo;

Bây giờ bạn đã thu gọn các chuỗi thành biểu diễn số nguyên. Nhưng thậm chí tốt hơn bạn có thể truy vấn chúng như trước đây.

SELECT *
FROM fulltextindexesarestupid
WHERE StopAbusingFeatures = 'Bad';

Điều này có tác dụng.

  1. che giấu sự thật rằng các danh mục của bạn là một loại liệt kê. Sự phức tạp đó được gói gọn trong loại và ẩn khỏi người dùng.
  2. nó cũng đặt bảo trì trên các loại trên loại.
  3. nó được chuẩn hóa.
  4. nó không tăng kích thước hàng.

Không có những lợi ích này, về cơ bản, bạn chỉ đang cố gắng tối ưu hóa việc so sánh chuỗi. Nhưng than ôi, tôi thậm chí không chắc làm thế nào sp_BlitzErik nhận được câu trả lời được cung cấp mã trong đề xuất,

like '%rock%' or
like '%paper%' or
like '%scisor%' or
like '%car%' or
like '%pasta%'

Bạn có thể thu gọn mã thông báo xuống số nguyên bằng cách sử dụng enum hoặc phương pháp cuộn bằng tay được đề xuất bởi sp_BlitzErik nhưng nếu bạn có thể thực hiện việc thu gọn thì tại sao bạn cũng làm như vậy? Tức là, nếu bạn biết '% pasta%' là mã thông báo 'pasta' tại sao bạn có %cả hai mặt của nó. Nếu không có '%' thì đây là một kiểm tra bình đẳng và nó sẽ khá nhanh ngay cả dưới dạng văn bản.

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.