"좋아요"또는 "좋아요"또는 "좋아요"또는 "좋아요"


10

이 질문에서 그는 나와 같은 문제를 겪고 있습니다. 나는 다음과 같은 것이 필요하다 :

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

이것은 추악하고 색인을 사용하지 않습니다.이 경우 실제로이 작업을 수행하는 유일한 방법이거나 (문자열 내에서 여러 단어를 선택하는 경우) FULLTEXT를 사용해야합니까?

내가 이해하는 것처럼 전체 텍스트를 사용하면 문자열 내에서 여러 단어를 선택할 수 있습니다.

이 질문은 전체 텍스트에 대해서도 이야기합니다.


3
제품 열의 데이터 유형은 무엇입니까? 평균 몇 자입니까?
Joe Obbish

답변:


17

전체 텍스트 색인은 일반적으로 마법의 총알이 아니며 추가 유지 관리, 디스크 공간 및 쿼리 패턴에 대한 상당한 변경이 필요합니다.

큰 문서 (이메일 본문, PDF, Word 문서 등)를 인덱싱해야 할 필요가 없다면 너무 과도합니다 (정직하다면 SQL Server에서 완전히 제거하고 Elasticsearch 또는 이와 유사한 것을 사용하십시오).

더 작은 사용 사례의 경우 일반적으로 계산 열이 더 나은 방법입니다.

빠른 데모 설정은 다음과 같습니다.

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)

비 지속 열을 기반으로 한 쿼리는 '인덱스 사용'과 모든 것을 제공하는 계획을 제공합니다. :)

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

견과류


-3

sp_BlitzErik의 답변 은 많은 좋은 점에 부딪치지 만 이것이 전체 텍스트 검색을 사용해서는 안되는 이유는 아닙니다. 전체 텍스트 검색은 당신이 생각하는 것을 수행하지 않습니다. 여러 필드를 검색 할 필요는 없습니다. 단어 내용을 벡터화하고 사전, 스터 빙, 어휘 분석기, 가제트, 중지 단어 제거 및 기타 적용되지 않는 많은 트릭을 사용합니다. 또는 아직 적용되지 않은 것으로 보입니다.

SQL Server 에서이 작업을 더 잘 수행하는 방법을 모르겠지만 솔루션에도 동의하지 않습니다. PostgreSQL에 대한 데이터를 다시 만들어 봅시다. PostgreSQL에서도 훨씬 깔끔합니다.

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;

이제 원하는 것은 열거 형입니다.

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

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

이제 문자열을 정수 표현으로 축소했습니다. 그러나 이전과 같이 쿼리하는 것이 더 좋습니다.

SELECT *
FROM fulltextindexesarestupid
WHERE StopAbusingFeatures = 'Bad';

효과가 있습니다.

  1. 카테고리라는 것이 열거 된 유형이라는 사실을 숨 깁니다. 이러한 복잡성은 유형으로 캡슐화되어 사용자에게 숨겨져 있습니다.
  2. 또한 해당 유형에 대한 유지 보수를 유형에 배치합니다.
  3. 표준화되었습니다.
  4. 행 크기가 커지지 않습니다.

이러한 이점이 없으면 본질적으로 문자열 비교를 최적화하려고합니다. 그러나 아아, 나는 제안에 코드가 주어지면 sp_BlitzErik이 어떻게 대답을 얻는 지 잘 모르겠습니다.

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

열거 형을 사용하거나 sp_BlitzErik에서 제안한 핸드 롤링 방법을 사용하여 토큰을 정수로 축소 할 수 있지만 축소를 수행 할 수있는 경우 왜 고정되지 않은 방식을 수행합니까? 즉, '% pasta %'가 'pasta'토큰이라는 것을 알고 있다면 %양쪽에 모두 왜 있어야합니까? '%'가 없으면 평등 확인이며 텍스트처럼 매우 빠릅니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.