“GİBİ VEYA GİBİ VEYA GİBİ VEYA GİBİ VEYA GİBİ” için daha iyi yaklaşım


10

Bu soruda benimle aynı problemi yaşıyor. Gibi bir şeye ihtiyacım var:

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

Bu çirkin ve dizinler kullanmıyor .. Bu durumda, bu gerçekten (bir dize içinde birden çok kelime seçmek için) tek yolu bu, ya da FULLTEXT kullanmalıyım?

Anladığım kadarıyla, tam metinle, bir dize içinde birden fazla kelime seçebilirim.

Bu soru Tam Metin hakkında da konuşuyor


3
Ürün sütununun veri türü nedir? Ortalama kaç karakter?
Joe Obbish

Yanıtlar:


17

Tam metin dizinleri genellikle sihirli bir madde işareti değildir ve ek bakım, disk alanı ve sorgu desenlerinde oldukça müdahaleci değişiklikler gerektirir.

Büyük belgeleri (e-posta gövdelerini, PDF'leri, Word belgelerini vb.) Dizine eklemeye gerçekten ihtiyacınız yoksa, aşırıya kaçarlar (ve dürüst olursak, bu işlemi tamamen SQL Server'dan çıkarırdım ve Elasticsearch veya benzeri bir şey kullanın).

Daha küçük kullanım durumları için hesaplanmış sütunlar genellikle daha iyi bir yaklaşımdır.

İşte hızlı bir demo kurulumu:

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)

Kalıcı olmayan bir sütuna bile dayalı sorgulama bize 'dizinleri kullanan' bir plan ve her şeyi verir :)

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

FINDIK


-3

sp_BlitzErik'in yanıtı birçok iyi noktaya ulaşıyor , ancak bu yüzden Tam Metin Arama'yı kullanmamanız gerektiğini düşünmüyorum. Tam metin araması, düşündüğünüzü yapmak için orada değildir. Birden fazla alanı aramak için orada değil. Kelime içeriğini vektörleştirmek ve sözlükleri, saplamaları, sözlükleri, gazeteleri, durma kelimelerini ortadan kaldırmayı ve hiçbiri geçerli olmayan diğer numaralardan yararlanmak için oradadır. Veya henüz başvurduğu gösterilmemiştir.

SQL Server'da bunu nasıl daha iyi yapacağımdan emin değilim de, çözümü de kabul etmiyorum. Verilerini PostgreSQL için yeniden oluşturalım - PostgreSQL'de oluşturmak çok daha temiz.

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;

Şimdi istediğiniz bir numaralandırma türü,

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

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

Şimdi dizeleri tamsayı gösterimine daralttınız. Ama daha iyisi onları daha önce olduğu gibi sorgulayabilirsiniz.

SELECT *
FROM fulltextindexesarestupid
WHERE StopAbusingFeatures = 'Bad';

Bunun etkisi var.

  1. kategorilerinizin numaralandırılmış bir tür olduğu gerçeğini gizler. Bu karmaşıklık tür içinde kapsüllenir ve kullanıcıdan gizlenir.
  2. ayrıca bu kategorilere bakım türüne yerleştirir.
  3. standartlaştırılmıştır.
  4. satır boyutunu büyütmez.

Bu avantajlar olmadan, temelde dize karşılaştırmasını optimize etmeye çalışıyorsunuz. Ama ne yazık ki, öneride kod verildiğinde sp_BlitzErik'in cevaba nasıl ulaştığından bile emin değilim,

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

Bir enum veya sp_BlitzErik tarafından önerilen el haddeleme yöntemini kullanarak belirteçleri tamsayılara daraltabilirsiniz, ancak daralmayı yapabiliyorsanız neden izinsiz benzeri yapıyorsunuz? Yani, '% makarna%' belirteç 'makarna' olduğunu biliyorsanız neden %her iki tarafında var. '%' Olmadan bu bir eşitlik kontrolü ve metin olarak bile oldukça hızlı olmalıdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.