2009-10-14 12 views
9

मेरे पास 117000 या तो रिकॉर्ड के साथ एक टेबल है। मुझे एक ऐसी खोज करने की ज़रूरत है जो दिए गए स्ट्रिंग पैटर्न के लिए 3 अलग-अलग फ़ील्ड की जांच करे।मैं एक TSQL "पसंद" खंड को अनुकूलित/पुन: सक्रिय कैसे कर सकता हूं?

मेरे जाता है, जहां खंड इस प्रकार है:

field1 LIKE '%' + @DESC + '%' 
OR field2 LIKE '%' + @DESC + '%' 
OR field3 LIKE '%' + @DESC + '%' 

इस इनपुट की परवाह किए बिना लगभग 24 सेकंड का समय लगता है ...

वहाँ यह करने के लिए एक बेहतर तरीका है? 10 से कम (या 5!) सेकंड अधिक बेहतर होगा।

किसी भी मदद के लिए धन्यवाद।

उत्तर

14

पूर्ण पाठ खोज और CONTAINS का उपयोग करें। क्षेत्र के बीच में खोज करते समय पसंद नहीं किया जा सकता है, यानी। जब LIKE अभिव्यक्ति '%' से शुरू होती है, तो यह हमेशा एक पूर्ण तालिका स्कैन करेगा।

+0

आप कर सकते हैं थोड़ा काम के साथ एक इंडेक्स का उपयोग करें, जब '%' + स्ट्रिंग करते समय, मेरी दूसरी टिप्पणी में लिंक देखें। –

+0

@ केएम: दिलचस्प चाल, एक उल्टा स्तंभ। फोन बुक के साथ भी अच्छा सादृश्य, मामला स्पष्ट रूप से स्पष्ट करता है। –

+0

अच्छी चाल, ओबाड के लिए '% text%' जैसी समस्या के समान कुछ भी नहीं है। – HLGEM

1

जब भी आप वाइल्डकार्ड के साथ एक खोज शुरू करते हैं, तो आप स्कैन कर रहे हैं। जब तक कि आप अपने खोज मानदंड को पहले वर्ण (जो संभव नहीं हो) शामिल करने के लिए संकीर्ण कर सकते हैं, आपको पूर्ण पाठ खोज का सहारा लेना होगा।

+3

@ स्टुअर्ट एन्सवर्थ ने कहा _ कभी भी आप वाइल्डकार्ड के साथ एक पसंद खोज शुरू करते हैं, आप एक स्कैन_ कर रहे हैं, इसलिए सोस को सच नहीं होना चाहिए, इसे देखें: http://stackoverflow.com/questions/1388059/sql-server-index -columns-used-in-like/1395881 # 1395881 –

+0

अब आप केवल अर्थशास्त्र के साथ खेल रहे हैं; आप कॉलम को पुनः प्राप्त करते हैं और इसे अनुक्रमित करते हैं, और उसके बाद इस तरह के खंड को उलट देते हैं, इसलिए यह वाइल्डकार्ड से शुरू नहीं होता है। आप वाइल्डकार्ड के साथ खोज शुरू नहीं कर रहे हैं, इसलिए आप स्कैन नहीं कर रहे हैं। मैं मानता हूं कि यह एक दिलचस्प समाधान है, और मुझे इसे ध्यान में रखना होगा। –

0

कैसे

के बारे में
field1 + field2 + field3 LIKE '%' + @DESC + '%' 

या

CONTAINS(field1 + field2 + field3, @DESC) 
1

तुम सच में एक वाइल्डकार्ड के साथ शुरू की जरूरत है? क्यूं कर? अक्सर आप कम से कम पहले अक्षर में टाइप करने के लिए उपयोगकर्ताओं को मजबूर कर सकते हैं। मैं इसे ऊपर लाता हूं क्योंकि कुछ डेवलपर्स सिर्फ वाइल्डकार्ड का उपयोग आदत के रूप में करते हैं क्योंकि इसकी आवश्यकता नहीं होती है। ज्यादातर मामलों में उपयोगकर्ता पहले अक्षर टाइप करने में सक्षम होंगे जब तक कि दायर स्टोर्स लंबे तार (जैसे आधिकारिक हवाई अड्डे के नाम कहें)। अन्यथा आपको वास्तव में पूर्ण-पाठ अनुक्रमण का उपयोग करने की आवश्यकता है हालांकि रिवर्स के साथ केएम की चाल बहुत अच्छी है यदि आपको अंत में वाइल्डकार्ड की आवश्यकता नहीं है।

यदि आप प्रदर्शन हत्या चीजों को करने से बच सकते हैं, तो ऐसा करें।

+0

हां, मुझे इस क्वेरी के लिए डबल पक्षीय वाइल्डकार्ड की आवश्यकता है। मुझे 'स्ट्रॉबेरी केला दही' में 'केले' जैसी कुछ चीज़ ढूंढनी है। – IronicMuffin

1

जबकि मैं स्वीकार किए गए उत्तर से सहमत हूं कि पूर्ण पाठ इंडेक्सिंग सबसे अच्छा समाधान होगा और यदि वे प्रदर्शन किया जाना है तो अग्रणी वाइल्डकार्ड खोजों के उपयोग की वकालत करने का कोई मतलब नहीं है तो संभावित कदम उठाए जा सकते हैं उनके प्रदर्शन को कम बुरा बनाओ।

Kalen पुस्तक में डेलाने "Microsoft SQL Server 2008 Internals" कहते हैं: जब एसक्यूएल सर्वर तार में लगभग सभी पात्रों देखने के लिए है

मिलान एक बहुत बड़ा अंतर बना सकते हैं। उदाहरण के लिए, निम्न को देखें:

SELECT COUNT(*) FROM tbl WHERE longcol LIKE '%abc%' 

यह एक nonbinary विंडोज मिलान से एक द्विआधारी मिलान के साथ 10 गुना तेजी से या अधिक निष्पादित कर सकते हैं। और varchar डेटा के साथ, यह Windows collation के मुकाबले SQL collation के साथ सात या आठ गुना तेजी से निष्पादित करता है।

+0

संयोजन कैसे प्रदर्शन को प्रभावित करता है? – crosenblum

+0

"यदि आपके पास वर्चर कॉलम है, तो आप इसे पर कॉल करके मजबूर कर सकते हैं: टीएलबी से COUNT (*) चुनें (जब) ​​लांगकॉल COLLATE SQL_Latin1_General_CP_CI_AS LIKE '% abc%';" –

+0

@yoelhalb आप शायद '_CP1_' नहीं '_CP_' – jazzcat

0

मैंने एक संभावित समाधान की कोशिश की। इस समाधान से पहले भी क्वेरी परिणाम वापस नहीं कर रही थी और कनेक्शन टाइमआउट त्रुटि उत्पन्न कर रही थी।

मेरी क्वेरी में तारीख फ़िल्टर और अन्य मानदंड थे।अन्य सभी मानदंड खोज की तरह थे। एक कॉलम कीवर्ड ntext कॉलम पर '% abc%' की तरह खोज रहा था और यह पूर्ण टेबल स्कैन कर रहा था।

समाधान:

2 भागों में क्वेरी विभाजित करें। 1) सीटीई (कॉमन टेबल एक्सप्रेस) में पहला हिस्सा 2) सीटीई पर सभी खोज मानदंडों को लागू करें।

WITH SearchData(Column1,Column2,Column3,Column4,........) 
    AS 
    (
    SELECT Column1,Column2,Column3,Column4,........... 
    FROM myTable1 WITH(NOLOCK) 
      INNER JOIN MyTable2 WITH(NOLOCK) 
       ON MyTable1.id = MyTable2.Id 
    WHERE (MyTable1.CreationTime >= '2014-04-27' AND MyTable1.CreationTime <= '2014-05-01') 
) 

    SELECT DISTINCT top 250 Column1,Column2,Column3,Column4 
    FROM SearchData 
    WHERE (ISNULL(Column1,'') LIKE @Column1 +'%' OR @Column1 IS NULL) 
      and (Column2 LIKE @Column2+ '%' OR @Column2 IS NULL) 
      ... 
      ... 
      ... 
      ... 
      AND (Column10 like '%'[email protected]+'%' or @Column10 IS NULL) 
      AND @[email protected][email protected][email protected] <> '' 
      ORDER BY [CreationTime] DESC 

यह मेरे लिए काम करता है।

+0

मुझे लगता है कि एक प्रश्न के साथ' TOP' खंड का उपयोग करना है जिसमें एक LIKE स्थिति हमेशा प्रदर्शन को बनाए रखेगी। तो यह सीटीई की बजाय शीर्ष क्लॉज है जो प्रदर्शन लाभ में योगदान देता है, क्योंकि शीर्ष के साथ रिकॉर्ड्स की आवश्यक संख्या स्कैन होने पर एक पूर्ण स्कैन को छोटा कर दिया जाता है। – Sunil

+1

प्रत्येक शामिल होने के साथ (एनओएलओकेके) का उपयोग कर ऑफ-विषय नोट के रूप में बहुत खतरनाक है, आपको इसके साथ बहुत सावधान रहना चाहिए या आपको डुप्लिकेट डेटा आदि मिलेगा ... मैं लोगों को इस संकेत को अनुकूलित करने के मानक तरीके के रूप में इस संकेत को उड़ाता हूं, इसकी नहीं।आपको हमेशा दो बार सोचना चाहिए और नोलॉक संकेत में ट्राइंग करने से पहले अपने आवेदन में टेबल लिखे गए (सम्मिलित/अपडेट) की समीक्षा करें। (बस केह रहा हू) –

0

यदि आप FullTextSearch का उपयोग नहीं कर सकते हैं तो आप 10 गुना गति बढ़ा सकते हैं। गणना क्षेत्र के लिए सूचकांक

alter table TableName 
add CalculatedColumnName as upper(Column1 + '|' + Column2...) collate Latin1_General_100_Bin2 
persisted; 

2 जोड़ें:: अगले कार्य करें:

1 जोड़ें गणना क्षेत्र आपकी क्वेरी पाठ

create nonclustered index IDX_TableName_CalculatedColumnName 
on TableName(CalculatedColumnName); 

3 बदलें

select count(*) 
from TableName 
where CalculatedColumnName like '%' + upper(@ParameterValue) + '%' collate Latin1_General_100_Bin2 

स्रोत: http://aboutsqlserver.com/2015/01/20/optimizing-substring-search-performance-in-sql-server

संबंधित मुद्दे