“LIKE OR LIKE, या LIKE, या LIKE, या LIKE” के लिए बेहतर तरीका


10

इस सवाल में वह वही समस्या है जो मैं हूं। मुझे कुछ इस तरह की आवश्यकता है:

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

यह बदसूरत है और यह अनुक्रमित का उपयोग नहीं कर रहा है .. इस मामले में, यह वास्तव में ऐसा करने का एकमात्र तरीका है (एक स्ट्रिंग के अंदर कई शब्दों का चयन करने के लिए), या मुझे FULLTEXT का उपयोग करना चाहिए?

जैसा कि मैं समझता हूं, फुलटेक्स्ट के साथ, मैं एक स्ट्रिंग के अंदर कई शब्दों का चयन कर सकता हूं।

यह प्रश्न पूर्ण पाठ के बारे में भी बात करता है


3
उत्पाद कॉलम का डेटा प्रकार क्या है? औसतन कितने अक्षर?
जो ओबिश

जवाबों:


17

पूर्ण पाठ अनुक्रमणिका आम तौर पर एक जादू की गोली नहीं है, और अतिरिक्त रखरखाव, डिस्क स्थान, और क्वेरी पैटर्न के लिए काफी घुसपैठ परिवर्तन की आवश्यकता होती है।

जब तक आपको वास्तव में बड़े दस्तावेज़ों को अनुक्रमित करने की आवश्यकता नहीं होती है (ईमेल बॉडीज़, पीडीएफ, वर्ड डॉक्स इत्यादि के बारे में सोचें), वे ओवरकिल हैं (और अगर हम ईमानदार हो रहे हैं, तो मैं उस प्रक्रिया को SQL सर्वर से पूरी तरह से ले लूंगा 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 सर्वर में बेहतर कैसे हो सकता है। चलिए 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%'

आप एक enum, या sp_BlitzErik द्वारा सुझाई गई हाथ-रोलिंग विधि का उपयोग करके टोकन को नीचे गिरा सकते हैं, लेकिन यदि आप ढहते हुए कर सकते हैं तो आप अनचाही तरह क्यों कर रहे हैं? यानी, यदि आप जानते हैं कि '% पास्ता%' एक टोकन 'पास्ता' है, तो आपके पास इसके %दोनों तरफ क्यों है । '%' के बिना यह एक समानता की जाँच करता है और इसे पाठ के रूप में भी बहुत तेज़ होना चाहिए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.