SQLite
 sql >> डेटाबेस >  >> RDS >> SQLite

पूर्ण यूनिकोड समर्थन के साथ SQLite में केस-असंवेदनशील खोज को लागू करने के 5 तरीके

हाल ही में मुझे यह जांचने के लिए SQLite में केस-असंवेदनशील खोज की आवश्यकता है कि मेरी परियोजनाओं में से एक में एक ही नाम वाला कोई आइटम पहले से मौजूद है या नहीं - listOK. सबसे पहले, यह एक आसान काम की तरह लग रहा था, लेकिन गहरे गोता लगाने पर, यह आसान हो गया, लेकिन बिल्कुल भी आसान नहीं, कई मोड़ और मोड़ के साथ।

अंतर्निहित SQLite क्षमताएं और उनकी कमियां

SQLite में आप केस-असंवेदनशील खोज तीन तरीकों से प्राप्त कर सकते हैं:

-- 1. Use a NOCASE collation
-- (we will look at other ways for applying collations later):
SELECT * 
    FROM items 
    WHERE text = "String in AnY case" COLLATE NOCASE;

-- 2. Normalize all strings to the same case,
-- does not matter lower or upper:
SELECT * 
    FROM items 
    WHERE LOWER(text) = "string in lower case";

-- 3. Use LIKE operator which is case insensitive by default:
SELECT * 
    FROM items 
    WHERE text LIKE "String in AnY case";

यदि आप SQLAlchemy और उसके ORM का उपयोग करते हैं तो ये दृष्टिकोण इस प्रकार दिखाई देंगे:

from sqlalchemy import func
from sqlalchemy.orm.query import Query

from package.models import YourModel


text_to_find = "Text in AnY case"

# NOCASE collation
Query(YourModel)
.filter(
    YourModel.field_name.collate("NOCASE") == text_to_find
)

# Normalizing text to the same case
Query(YourModel)
.filter(
    func.lower(YourModel.field_name) == text_to_find.lower()
).all()

# LIKE operator. No need to use SQLAlchemy's ilike
# since SQLite LIKE is already case-insensitive.
Query(YourModel)
.filter(YourModel.field_name.like(text_to_find))

ये सभी दृष्टिकोण आदर्श नहीं हैं। पहले , विशेष विचार के बिना वे LIKE के साथ, जिस क्षेत्र में वे काम कर रहे हैं, उस पर अनुक्रमणिका का उपयोग नहीं करते हैं सबसे खराब अपराधी होने के नाते:ज्यादातर मामलों में यह इंडेक्स का उपयोग करने में असमर्थ है। केस-असंवेदनशील प्रश्नों के लिए अनुक्रमणिका के उपयोग के बारे में अधिक जानकारी नीचे दी गई है।

दूसरा , और इससे भी महत्वपूर्ण बात यह है कि उन्हें केस-असंवेदनशील अर्थ की अपेक्षाकृत सीमित समझ है:

<ब्लॉकक्वॉट>

SQLite डिफ़ॉल्ट रूप से केवल ASCII वर्णों के लिए ऊपरी/निचले मामले को समझता है। LIKE ऑपरेटर केस संवेदनशील . है यूनिकोड वर्णों के लिए डिफ़ॉल्ट रूप से जो ASCII सीमा से परे हैं। उदाहरण के लिए, व्यंजक 'a' LIKE 'A' TRUE है लेकिन 'æ' LIKE 'Æ' FALSE है।

यह कोई समस्या नहीं है यदि आप उन स्ट्रिंग्स के साथ काम करने की योजना बना रहे हैं जिनमें केवल अंग्रेजी वर्णमाला के अक्षर, संख्याएँ आदि हैं। मुझे पूर्ण यूनिकोड स्पेक्ट्रम की आवश्यकता थी, इसलिए एक बेहतर समाधान क्रम में था।

नीचे मैं सभी यूनिकोड प्रतीकों के लिए SQLite में केस असंवेदनशील खोज/तुलना प्राप्त करने के पांच तरीकों का सारांश देता हूं। इनमें से कुछ समाधान अन्य डेटाबेस के लिए अनुकूलित किए जा सकते हैं और यूनिकोड-जागरूक LIKE . को लागू करने के लिए , REGEXP , MATCH , और अन्य कार्य, हालांकि ये विषय इस पोस्ट के दायरे से बाहर हैं।

हम प्रत्येक दृष्टिकोण, कार्यान्वयन विवरण, और अंत में, अनुक्रमित और प्रदर्शन विचारों के पेशेवरों और विपक्षों को देखेंगे।

समाधान

1. आईसीयू एक्सटेंशन

आधिकारिक SQLite दस्तावेज़ीकरण ICU एक्सटेंशन का उल्लेख SQLite में यूनिकोड के लिए पूर्ण समर्थन जोड़ने के तरीके के रूप में करता है। ICU का मतलब यूनिकोड के लिए अंतर्राष्ट्रीय घटक हैं।

आईसीयू केस-असंवेदनशील LIKE दोनों की समस्याओं का समाधान करता है और तुलना/खोज, प्लस एक अच्छे उपाय के लिए विभिन्न संयोजनों के लिए समर्थन जोड़ता है। यह बाद के कुछ समाधानों से भी तेज़ हो सकता है क्योंकि यह C में लिखा गया है और SQLite के साथ अधिक मजबूती से एकीकृत है।

हालाँकि, यह अपनी चुनौतियों के साथ आता है:

  1. यह एक नया प्रकार है निर्भरता का:पायथन पुस्तकालय नहीं, बल्कि एक विस्तार जिसे आवेदन के साथ वितरित किया जाना चाहिए।

  2. उपयोग से पहले आईसीयू को संकलित करने की आवश्यकता है, संभावित रूप से विभिन्न ओएस और प्लेटफॉर्म के लिए (परीक्षण नहीं किया गया)।

  3. आईसीयू स्वयं यूनिकोड रूपांतरणों को लागू नहीं करता है, लेकिन अंडरलाइन ऑपरेटिंग सिस्टम पर निर्भर करता है - मैंने ओएस-विशिष्ट मुद्दों के कई उल्लेख देखे हैं, विशेष रूप से विंडोज और मैकओएस के साथ।

अन्य सभी समाधान तुलना करने के लिए आपके पायथन कोड पर निर्भर होंगे, इसलिए स्ट्रिंग्स को बदलने और तुलना करने के लिए सही दृष्टिकोण चुनना महत्वपूर्ण है।

केस-असंवेदनशील तुलना के लिए सही पायथन फ़ंक्शन चुनना

केस-असंवेदनशील तुलना और खोज करने के लिए हमें एक मामले में स्ट्रिंग्स को सामान्य करने की आवश्यकता है। मेरी पहली प्रवृत्ति str.lower() . का उपयोग करने की थी इसके लिए। यह ज्यादातर परिस्थितियों में काम करेगा, लेकिन यह उचित तरीका नहीं है। उपयोग करने के लिए बेहतर है str.casefold() (दस्तावेज़):

<ब्लॉकक्वॉट>

स्ट्रिंग की केस फोल्डेड कॉपी लौटाएं। केस-फोल्डेड स्ट्रिंग्स का उपयोग केसलेस मिलान के लिए किया जा सकता है।

केसफोल्डिंग लोअरकेसिंग के समान है लेकिन अधिक आक्रामक है क्योंकि इसका उद्देश्य स्ट्रिंग में सभी केस भेदों को हटाना है। उदाहरण के लिए, जर्मन लोअरकेस अक्षर 'ß' "ss" के बराबर है। चूंकि यह पहले से ही लोअरकेस है, lower() 'ß' के लिए कुछ नहीं करेंगे; casefold() इसे "ss" में बदल देता है।

इसलिए, नीचे हम str.casefold() . का प्रयोग करेंगे सभी रूपांतरणों और तुलनाओं के लिए कार्य करता है।

2. अनुप्रयोग-परिभाषित संयोजन

सभी यूनिकोड प्रतीकों के लिए केस-असंवेदनशील खोज करने के लिए हमें डेटाबेस (दस्तावेज़ीकरण) से कनेक्ट होने के बाद एप्लिकेशन में एक नया संयोजन परिभाषित करना होगा। यहां आपके पास एक विकल्प है - बिल्ट-इन NOCASE . को ओवरलोड करें या अपना खुद का बनाएं - हम नीचे पेशेवरों और विपक्षों पर चर्चा करेंगे। एक उदाहरण के लिए हम एक नए नाम का प्रयोग करेंगे:

import sqlite3

# Custom collation, maybe it is more efficient
# to store strings
def unicode_nocase_collation(a: str, b: str):
    if a.casefold() == b.casefold():
        return 0
    if a.casefold() < b.casefold():
        return -1
    return 1

connection.create_collation(
    "UNICODE_NOCASE", unicode_nocase_collation
)

# Connect to the DB and register the function
connection = sqlite3.connect("your_db_path")
connection.create_collation(
    "UNICODE_NOCASE", unicode_nocase_collation
)

# Or, if you use SQLAlchemy you need to register
# the collation via an event
@sa.event.listens_for(sa.engine.Engine, 'connect')
def sqlite_engine_connect(connection, _):
    connection.create_collation(
    "UNICODE_NOCASE", unicode_nocase_collation
)

अगले समाधानों की तुलना में Collations के कई फायदे हैं:

  1. वे प्रयोग करने में आसान हैं। आप तालिका स्कीमा में संयोजन निर्दिष्ट कर सकते हैं और यह स्वचालित रूप से इस फ़ील्ड पर सभी प्रश्नों और अनुक्रमणिकाओं पर लागू हो जाएगा जब तक कि आप अन्यथा निर्दिष्ट न करें:

    CREATE TABLE test (text VARCHAR COLLATE UNICODE_NOCASE);
    

    पूर्णता के लिए, आइए कॉलेशन का उपयोग करने के दो और तरीके देखें:

    -- In a particular query:
    SELECT * FROM items
        WHERE text = "Text in AnY case" COLLATE UNICODE_NOCASE;
    
    -- In an index:
    CREATE INDEX IF NOT EXISTS idx1 
        ON test (text COLLATE UNICODE_NOCASE);
    
    -- Word of caution: your query and index 
    -- must match exactly,including collation, 
    -- otherwise, SQLite will perform a full table scan.
    -- More on indexes below.
    EXPLAIN QUERY PLAN
        SELECT * FROM test WHERE text = 'something';
    -- Output: SCAN TABLE test
    EXPLAIN QUERY PLAN
        SELECT * FROM test WHERE text = 'something' COLLATE NOCASE;
    -- Output: SEARCH TABLE test USING COVERING INDEX idx1 (text=?)
    
  2. Collation ORDER BY . के साथ केस-असंवेदनशील सॉर्टिंग प्रदान करता है अलग सोच। यदि आप तालिका स्कीमा में संयोजन को परिभाषित करते हैं तो इसे प्राप्त करना विशेष रूप से आसान है।

प्रदर्शन-वार संयोजनों में कुछ ख़ासियतें होती हैं, जिनके बारे में हम आगे चर्चा करेंगे।

3. अनुप्रयोग-परिभाषित SQL फ़ंक्शन

केस-असंवेदनशील खोज प्राप्त करने का दूसरा तरीका एप्लिकेशन-परिभाषित SQL फ़ंक्शन (दस्तावेज़ीकरण) बनाना है:

import sqlite3

# Custom function
def casefold(s: str):
    return s.casefold()

# Connect to the DB and register the function
connection = sqlite3.connect("your_db_path")
connection.create_function("CASEFOLD", 1, casefold)

# Or, if you use SQLAlchemy you need to register 
# the function via an event
@sa.event.listens_for(sa.engine.Engine, 'connect')
def sqlite_engine_connect(connection, _):
    connection.create_function("CASEFOLD", 1, casefold)

दोनों ही मामलों में create_function अधिकतम चार तर्क स्वीकार करता है:

  • फ़ंक्शन का नाम जैसा कि SQL क्वेरी में उपयोग किया जाएगा
  • फ़ंक्शन द्वारा स्वीकार किए जाने वाले तर्कों की संख्या
  • स्वयं फ़ंक्शन
  • वैकल्पिक बूल deterministic , डिफ़ॉल्ट False (पायथन 3.8 में जोड़ा गया) - यह इंडेक्स के लिए महत्वपूर्ण है, जिसके बारे में हम नीचे चर्चा करेंगे।

कोलाजेशन की तरह, आपके पास एक विकल्प है - बिल्ट-इन फंक्शन को ओवरलोड करें (उदाहरण के लिए, LOWER ) या नया बनाएँ। हम इसे बाद में और विस्तार से देखेंगे।

4. एप्लिकेशन में तुलना करें

केस-असंवेदनशील खोज का एक अन्य तरीका ऐप में ही तुलना करना होगा, खासकर यदि आप अन्य क्षेत्रों पर एक इंडेक्स का उपयोग करके खोज को कम कर सकते हैं। उदाहरण के लिए, सूची में किसी विशेष सूची में आइटम के लिए ओके केस-असंवेदनशील तुलना की आवश्यकता होती है। इसलिए, मैं सूची में सभी वस्तुओं का चयन कर सकता हूं, उन्हें एक मामले में सामान्य कर सकता हूं और उनकी तुलना सामान्यीकृत नए आइटम से कर सकता हूं।

आपकी परिस्थितियों के आधार पर यह एक बुरा समाधान नहीं है, खासकर यदि आप जिस उपसमुच्चय से तुलना करेंगे वह छोटा है। हालांकि, आप टेक्स्ट पर डेटाबेस इंडेक्स का उपयोग करने में सक्षम नहीं होंगे, केवल अन्य पैरामीटर पर आप दायरे को कम करने के लिए उपयोग करेंगे।

इस दृष्टिकोण का लाभ इसकी लचीलापन है:आवेदन में आप न केवल समानता की जांच कर सकते हैं बल्कि, उदाहरण के लिए, संभावित गलत प्रिंट, एकवचन/बहुवचन रूपों आदि को ध्यान में रखते हुए "फजी" तुलना को कार्यान्वित कर सकते हैं। यह वह मार्ग है जिसे मैंने सूची के लिए चुना है। चूंकि बॉट को "स्मार्ट" आइटम निर्माण के लिए अस्पष्ट तुलना की आवश्यकता थी।

इसके अलावा, यह डेटाबेस के साथ किसी भी युग्मन को समाप्त करता है - यह सरल भंडारण है जो डेटा के बारे में कुछ भी नहीं जानता है।

5. सामान्यीकृत फ़ील्ड को अलग से स्टोर करें

एक और समाधान है:डेटाबेस में एक अलग कॉलम बनाएं और वहां सामान्यीकृत टेक्स्ट रखें जिसे आप खोज रहे होंगे। उदाहरण के लिए, तालिका में यह संरचना हो सकती है (केवल प्रासंगिक फ़ील्ड):

<थ>नाम
आईडी name_normalized
1 वाक्य कैपिटलाइज़ेशन वाक्य कैपिटलाइज़ेशन
2 बड़े अक्षर बड़े अक्षर
3 गैर-ASCII प्रतीक:Найди Меня गैर-ascii प्रतीक:найди меня

यह पहली बार में अत्यधिक लग सकता है:आपको सामान्यीकृत संस्करण को हमेशा अद्यतन रखने और name के आकार को प्रभावी ढंग से दोगुना करने की आवश्यकता है खेत। हालांकि, ओआरएम के साथ या यहां तक ​​कि मैन्युअल रूप से यह करना आसान है और डिस्क स्थान प्लस रैम सापेक्षता सस्ता है।

इस दृष्टिकोण के लाभ:

  • यह एप्लिकेशन और डेटाबेस को पूरी तरह से अलग कर देता है - आप आसानी से स्विच कर सकते हैं।

  • यदि आपके प्रश्नों के लिए इसकी आवश्यकता है तो आप सामान्यीकृत फ़ाइल को पूर्व-संसाधित कर सकते हैं (ट्रिम करें, विराम चिह्न या रिक्त स्थान हटाएं, आदि)।

क्या आपको बिल्ट-इन फंक्शन और कॉलेशन को ओवरलोड करना चाहिए?

एप्लिकेशन-परिभाषित SQL फ़ंक्शंस और कॉलेशन का उपयोग करते समय आपके पास अक्सर एक विकल्प होता है:एक अद्वितीय नाम का उपयोग करें या अंतर्निहित कार्यक्षमता को अधिभारित करें। दोनों दृष्टिकोणों के दो मुख्य आयामों में उनके पक्ष और विपक्ष हैं:

सबसे पहले, विश्वसनीयता/पूर्वानुमानितता जब किसी कारण से (एक बार की गलती, बग, या जानबूझकर) आप इन कार्यों या कॉलेशन को पंजीकृत नहीं करते हैं:

  • ओवरलोडिंग:डेटाबेस अभी भी काम करेगा, लेकिन हो सकता है कि परिणाम सही न हों:

    • अंतर्निहित फ़ंक्शन/संयोजन उनके कस्टम समकक्षों की तुलना में अलग व्यवहार करेगा;
    • यदि आप किसी अनुक्रमणिका में अब अनुपस्थित संयोजन का उपयोग करते हैं तो यह काम करता प्रतीत होगा, लेकिन परिणाम पढ़ते समय भी गलत हो सकता है;
    • यदि कस्टम फ़ंक्शन/कोलेशन का उपयोग कर इंडेक्स और इंडेक्स वाली तालिका अपडेट हो जाती है, तो इंडेक्स दूषित हो सकता है (अंतर्निहित कार्यान्वयन का उपयोग करके अपडेट किया गया), लेकिन काम करना जारी रखें जैसे कि कुछ भी नहीं हुआ।
  • ओवरलोडिंग नहीं:डेटाबेस किसी भी तरह से काम नहीं करेगा जहां अनुपस्थित फ़ंक्शन या कॉलेशन का उपयोग किया जाता है:

    • यदि आप किसी अनुपस्थित फ़ंक्शन पर किसी अनुक्रमणिका का उपयोग करते हैं तो आप इसे पढ़ने के लिए उपयोग करने में सक्षम होंगे, लेकिन अपडेट के लिए नहीं;
    • अनुप्रयोग-परिभाषित संयोजन वाली अनुक्रमणिकाएँ बिल्कुल भी काम नहीं करेंगी, क्योंकि वे अनुक्रमणिका में खोज करते समय संयोजन का उपयोग करती हैं।

दूसरा, पहुंच-योग्यता मुख्य एप्लिकेशन के बाहर:माइग्रेशन, विश्लेषण, आदि:

  • ओवरलोडिंग:आप इंडेक्स को दूषित करने के जोखिम को ध्यान में रखते हुए बिना किसी समस्या के डेटाबेस को संशोधित करने में सक्षम होंगे।

  • ओवरलोडिंग नहीं:कई मामलों में आपको इन कार्यों या कॉलेशन को पंजीकृत करना होगा या डेटाबेस के उन हिस्सों से बचने के लिए अतिरिक्त कदम उठाने होंगे जो इस पर निर्भर हैं।

यदि आप ओवरलोड करने का निर्णय लेते हैं, तो कस्टम फ़ंक्शंस या कॉलेशन के आधार पर इंडेक्स को फिर से बनाना एक अच्छा विचार हो सकता है, यदि वे वहां गलत डेटा दर्ज करते हैं, उदाहरण के लिए:

-- Rebuild all indexes using this collation
REINDEX YOUR_COLLATION_NAME;

-- Rebuild particular index
REINDEX index_name;

-- Rebuild all indexes
REINDEX;

अनुप्रयोग-परिभाषित कार्यों और संयोजनों का प्रदर्शन

कस्टम फ़ंक्शंस या कॉलेशन बिल्ट-इन फ़ंक्शंस की तुलना में बहुत धीमे होते हैं:SQLite हर बार फ़ंक्शन को कॉल करने पर आपके एप्लिकेशन पर "रिटर्न" करता है। आप फ़ंक्शन में वैश्विक काउंटर जोड़कर इसे आसानी से देख सकते हैं:

counter = 0

def casefold(a: str):
    global counter
    counter += 1
    return a.casefold()

# Work with the database

print(counter)
# Number of times the function has been called

यदि आप शायद ही कभी पूछताछ कर रहे हैं या आपका डेटाबेस छोटा है, तो आपको कोई सार्थक अंतर नहीं दिखाई देगा। हालाँकि, यदि आप इस फ़ंक्शन/संयोजन पर किसी अनुक्रमणिका का उपयोग नहीं करते हैं, तो डेटाबेस प्रत्येक पंक्ति पर फ़ंक्शन/संयोजन को लागू करते हुए एक पूर्ण तालिका स्कैन कर सकता है। तालिका के आकार, हार्डवेयर और अनुरोधों की संख्या के आधार पर, निम्न प्रदर्शन आश्चर्यजनक हो सकता है। बाद में मैं एप्लिकेशन-परिभाषित कार्यों और कॉलेशन प्रदर्शन की समीक्षा प्रकाशित करूंगा।

कड़ाई से बोलते हुए, एसक्यूएल फ़ंक्शंस की तुलना में कोलाज थोड़ा धीमा होता है क्योंकि प्रत्येक तुलना के लिए उन्हें एक के बजाय दो स्ट्रिंग्स को केसफोल्ड करने की आवश्यकता होती है। हालांकि यह अंतर बहुत छोटा है:मेरे परीक्षणों में, केसफोल्ड फ़ंक्शन लगभग 25% के समान संयोजन की तुलना में तेज़ था, जो कि 100 मिलियन पुनरावृत्तियों के बाद 10 सेकंड के अंतर के बराबर था।

अनुक्रमणिका और केस-संवेदी खोज

अनुक्रमणिका और कार्य

आइए बुनियादी बातों से शुरू करें:यदि आप किसी भी क्षेत्र पर एक सूचकांक को परिभाषित करते हैं, तो इसका उपयोग इस क्षेत्र में लागू किसी फ़ंक्शन पर प्रश्नों में नहीं किया जाएगा:

CREATE TABLE table_name (id INTEGER, name VARCHAR);
CREATE INDEX idx1 ON table_name (name);
EXPLAIN QUERY PLAN
    SELECT id, name FROM table_name WHERE LOWER(name) = 'test';
-- Output: SCAN TABLE table_name

ऐसे प्रश्नों के लिए आपको फ़ंक्शन के साथ एक अलग अनुक्रमणिका की आवश्यकता होती है:

CREATE INDEX idx1 ON table_name (LOWER(name));
EXPLAIN QUERY PLAN
    SELECT id, name 
        FROM table_name WHERE LOWER(name) = 'test';
-- Output: SEARCH TABLE table_name USING INDEX idx1 (<expr>=?)

SQLite में, यह एक कस्टम फ़ंक्शन पर भी किया जा सकता है, लेकिन इसे नियतात्मक के रूप में चिह्नित किया जाना चाहिए (जिसका अर्थ है कि समान इनपुट के साथ यह समान परिणाम देता है):

connection.create_function(
    "CASEFOLD", 1, casefold, deterministic=True
)

उसके बाद आप एक कस्टम SQL फ़ंक्शन पर एक अनुक्रमणिका बना सकते हैं:

CREATE INDEX idx1 
    ON table_name (CASEFOLD(name));
EXPLAIN QUERY PLAN
    SELECT id, name 
        FROM table_name WHERE CASEFOLD(name) = 'test';
-- Output: SEARCH TABLE table_name USING INDEX idx1 (<expr>=?)

अनुक्रमणिका और संयोजन

कोलाज और इंडेक्स के साथ स्थिति समान है:किसी इंडेक्स का उपयोग करने के लिए एक क्वेरी के लिए उन्हें उसी कॉलेशन का उपयोग करना चाहिए (निहित या स्पष्ट रूप से प्रदान किया गया), अन्यथा, यह काम नहीं करेगा।

-- Table without specified collation will use BINARY
CREATE TABLE test (id INTEGER, text VARCHAR);

-- Create an index with a different collation
CREATE INDEX IF NOT EXISTS idx1 ON test (text COLLATE NOCASE);


-- Query will use default column collation -- BINARY
-- and the index will not be used
EXPLAIN QUERY PLAN
    SELECT * FROM test WHERE text = 'test';
-- Output: SCAN TABLE test


-- Now collations match and index is used
EXPLAIN QUERY PLAN
    SELECT * FROM test WHERE text = 'test' COLLATE NOCASE;
-- Output: SEARCH TABLE test USING INDEX idx1 (text=?)

जैसा कि ऊपर उल्लेख किया गया है, तालिका स्कीमा में एक कॉलम के लिए संयोजन निर्दिष्ट किया जा सकता है। यह सबसे सुविधाजनक तरीका है - जब तक आप अन्यथा निर्दिष्ट नहीं करते हैं, तब तक यह संबंधित फ़ील्ड पर सभी प्रश्नों और अनुक्रमणिकाओं पर स्वचालित रूप से लागू होगा:

-- Using application defined collation UNICODE_NOCASE from above
CREATE TABLE test (text VARCHAR COLLATE UNICODE_NOCASE);

-- Index will be built using the collation
CREATE INDEX idx1 ON test (text);

-- Query will utilize index and collation automatically
EXPLAIN QUERY PLAN
    SELECT * FROM test WHERE text = 'something';
-- Output: SEARCH TABLE test USING COVERING INDEX idx1 (text=?)

कौन सा समाधान चुनना है?

समाधान चुनने के लिए हमें तुलना के लिए कुछ मानदंड चाहिए:

  1. सादगी - इसे लागू करना और बनाए रखना कितना मुश्किल है

  2. प्रदर्शन - आपके प्रश्न कितने तेज़ होंगे

  3. अतिरिक्त स्थान - समाधान के लिए कितने अतिरिक्त डेटाबेस स्थान की आवश्यकता है

  4. युग्मन - आपका समाधान कोड और संग्रहण को कितना जोड़ता है

समाधान सादगी प्रदर्शन (सापेक्ष, बिना अनुक्रमणिका के) अतिरिक्त स्थान युग्मन
आईसीयू एक्सटेंशन मुश्किल:एक नए प्रकार की निर्भरता और संकलन की आवश्यकता है मध्यम से उच्च नहीं हां
कस्टम संयोजन सरल:तालिका स्कीमा में संयोजन सेट करने और फ़ील्ड पर किसी भी क्वेरी पर इसे स्वचालित रूप से लागू करने की अनुमति देता है निम्न नहीं हां
कस्टम SQL फ़ंक्शन माध्यम:या तो इसके आधार पर एक इंडेक्स बनाने या सभी प्रासंगिक प्रश्नों में उपयोग करने की आवश्यकता है निम्न नहीं हां
ऐप में तुलना करना सरल उपयोग के मामले पर निर्भर करता है नहीं नहीं
सामान्यीकृत स्ट्रिंग संग्रहित करना मध्यम:आपको सामान्यीकृत स्ट्रिंग को अद्यतन रखने की आवश्यकता है निम्न से मध्यम x2 नहीं

हमेशा की तरह, समाधान का चुनाव आपके उपयोग के मामले और प्रदर्शन की मांगों पर निर्भर करेगा। व्यक्तिगत रूप से, मैं या तो कस्टम संयोजन के साथ जाऊंगा, ऐप में तुलना करूंगा, या एक सामान्यीकृत स्ट्रिंग संग्रहीत करूंगा। उदाहरण के लिए, लिस्ट ओके में, मैंने पहली बार एक कोलेशन का इस्तेमाल किया और फजी सर्च को जोड़ने पर ऐप में तुलना करने के लिए आगे बढ़ा।


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. android.database.sqlite.SQLiteCantOpenDatabaseException:अज्ञात त्रुटि (कोड 14):डेटाबेस नहीं खोल सका

  2. SQLite डेटाबेस से एक छवि कैसे पुनर्प्राप्त करें?

  3. निर्माणकर्ता SQLiteOpenHelper() अपरिभाषित है

  4. SQLite डेटाबेस को पुनर्स्थापित करें

  5. सेवा के रुकने पर गतिविधि डेटा अपडेट करें