MySQL में सशर्त सूचकांक कैसे बनाएं?


24

MySQL में किसी विशिष्ट रेंज या टेबल के सबसेट को फ़िल्टर करने के लिए एक इंडेक्स कैसे बनाएं? AFAIK को सीधे बनाना असंभव है, लेकिन मुझे लगता है कि इस सुविधा का अनुकरण करना संभव है।

उदाहरण: मैं NAMEकेवल पंक्तियों के लिए कॉलम के लिए एक सूचकांक बनाना चाहता हूंSTATUS = 'ACTIVE'

यह कार्यक्षमता SQL सर्वर में फ़िल्टर किए गए अनुक्रमणिका और Postgres में एक आंशिक अनुक्रमणिका कहलाएगी।

जवाबों:


9

MySQL वर्तमान में सशर्त अनुक्रमित का समर्थन नहीं करता है।

यह पूछने के लिए कि आप क्या पूछ रहे हैं (ऐसा नहीं है कि आपको यह करना चाहिए;)) आप एक सहायक तालिका बनाना शुरू कर सकते हैं:

CREATE TABLE  `my_schema`.`auxiliary_table` (
   `id` int unsigned NOT NULL,
   `name` varchar(250), /* specify the same way as in your main table */
   PRIMARY KEY (`id`),
   KEY `name` (`name`)
);

फिर आप मुख्य तालिका में तीन ट्रिगर जोड़ते हैं:

delimiter //

CREATE TRIGGER example_insert AFTER INSERT ON main_table
FOR EACH ROW
BEGIN
   IF NEW.status = 'ACTIVE' THEN
      REPLACE auxiliary_table SET
         auxiliary_table.id = NEW.id,
         auxiliary_table.name = NEW.name;
   END IF;
END;//

CREATE TRIGGER example_update AFTER UPDATE ON main_table
FOR EACH ROW
BEGIN
   IF NEW.status = 'ACTIVE' THEN
      REPLACE auxiliary_table SET
         auxiliary_table.id = NEW.id,
         auxiliary_table.name = NEW.name;
   ELSE
      DELETE FROM auxiliary_table WHERE auxiliary_table.id = OLD.id;
   END IF;
END;//

CREATE TRIGGER example_delete AFTER DELETE ON main_table
FOR EACH ROW
BEGIN
   DELETE FROM auxiliary_table WHERE auxiliary_table.id = OLD.id;
END;//

delimiter ;

हमें आवश्यकता है delimiter //क्योंकि हम ;ट्रिगर्स के अंदर उपयोग करना चाहते हैं ।

इस प्रकार, सहायक तालिका में मुख्य तालिका पंक्तियों के अनुरूप आईडी होगी जिसमें स्ट्रिंग "सक्रिय" होता है, जिसे ट्रिगर्स द्वारा अद्यतन किया जा रहा है।

उस पर उपयोग करने के लिए select, आप सामान्य रूप से उपयोग कर सकते हैं join:

SELECT main_table.* FROM auxiliary_table LEFT JOIN main_table
   ON auxiliary_table.id = main_table.id
   ORDER BY auxiliary_table.name;

यदि मुख्य तालिका में पहले से ही डेटा है, या यदि आप कुछ बाहरी ऑपरेशन करते हैं जो डेटा को असामान्य तरीके से बदलता है (जैसे: MySQL के बाहर), तो आप इसके साथ सहायक तालिका को ठीक कर सकते हैं:

INSERT INTO auxiliary_table SET
   id = main_table.id,
   name = main_table.name,
   WHERE main_table.status="ACTIVE";

प्रदर्शन के बारे में, शायद आपके पास धीमे आवेषण, अपडेट और हटाए गए होंगे। यह केवल तभी समझ में आता है जब आप वास्तव में कुछ मामलों से निपटते हैं जहां वांछित स्थिति सकारात्मक होती है। यहां तक ​​कि इस तरह, शायद केवल आप देख सकते हैं कि क्या बचाया गया स्थान वास्तव में इस aproach को सही ठहराता है (और यदि आप वास्तव में किसी भी स्थान को बचा रहे हैं)।


7

यदि मैं प्रश्न को सही ढंग से समझता हूं, तो मुझे लगता है कि आप जो करना चाहते हैं उसे पूरा करेंगे, दोनों कॉलम, NAME और STATUS पर एक इंडेक्स बनाना है। यह आपको कुशलता से क्वेरी करने की अनुमति देगा जहाँ NAME = 'SMITH' और STATUS = 'ACTIVE'


1
ठीक है, लेकिन यह स्थान कुशल नहीं है यदि आपके पास स्थिति के साथ अपेक्षाकृत कुछ लाइनें हैं।
मणिएरो

नहीं, यह नहीं है, लेकिन यह सवाल में एक आवश्यकता नहीं थी, और यह नहीं कहा गया था कि तालिका में मूल्यों में से एक को भारी भारित किया गया था। उसके लिए मैं आपके द्वारा खोजे जा रहे STATUS का एक भौतिक दृश्य बनाऊंगा, लेकिन MySQL उन का समर्थन नहीं करता है।
BlackICE

और डिस्क स्थान सस्ता है ...
BlackICE

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

मैं स्मृति पर भी असहमत होऊंगा, यह इन दिनों बहुत सस्ता है (निश्चित रूप से डिस्क स्थान जितना सस्ता नहीं है, लेकिन $ 10 / गीग में कुछ के लिए, मैं कहूंगा कि आप थोड़ा आराम कर सकते हैं :)
ब्लैकिस

6

आप सशर्त अनुक्रमण नहीं कर सकते, लेकिन अपने उदाहरण के लिए, आप ( name, status) पर एक बहु-स्तंभ अनुक्रमणिका जोड़ सकते हैं ।

भले ही यह उन स्तंभों में सभी डेटा को अनुक्रमित करेगा, फिर भी यह आपको उन नामों को खोजने में मदद करेगा जिन्हें आप "सक्रिय" स्थिति के साथ देख रहे हैं।


4

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

दुर्भाग्य से अंतर्निहित तालिका विभाजन सुविधा आपकी खोज में आपकी मदद नहीं करेगी क्योंकि आप एक एकल विभाजन के लिए एक सूचकांक लागू नहीं कर सकते।

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


मैं दो तालिकाओं के लिए बेहतर अनुक्रमण नहीं कर सकता, क्योंकि यह अभी भी महंगा होगा न?
jcolebrand

@jcolebrand: सामान्य प्रश्नों के लिए यह अधिक महंगा होगा (एक संघ करने वाले विचारों पर), आपको विशेष रूप से सूचकांक का उपयोग करने के लिए विभाजन तालिका से चयन करना होगा। अंतर्निहित विभाजन आपके लिए कुशलतापूर्वक ऐसा करेगा, लेकिन केवल Bigown चाहता है (अंतरिक्ष को बचाने के लिए) यदि यह विभाजन विशिष्ट अनुक्रमित का समर्थन करता है। मैंने कहा कि वह ऐसा कर सकता है, ऐसा नहीं कि वह करना चाहेगा!
डेविड स्पिललेट

0

MySQL में अब वर्चुअल कॉलम हैं, जिन्हें इंडेक्स के लिए इस्तेमाल किया जा सकता है।


3
फ़िल्टर किए गए इंडेक्स का अनुकरण करने के लिए इस सुविधा का उपयोग कैसे किया जा सकता है?
ypercube y

1
@ yper-trollᵀᴹ, druud62 ओरेकल के बारे में सोच रहे होंगे: dbfiddle.uk/… - MySQL ने NULLs के साथ वैसा ही व्यवहार नहीं किया है: dbfiddle.uk/…
जैक डगलस

@ जेकडौगलस शायद। (क्या यह सिर्फ एक इंडेक्स ऑप्टिमाइज़ेशन नहीं है, जो स्पेस को रास्ते से बचाता है? दूसरे शब्दों में select count(*) from foo where id is null ;इंडेक्स का इस्तेमाल कर सकता है ?)
ypercube17

@ yper-trollᵀᴹ Oracle उन पंक्तियों को अनुक्रमणित नहीं करता है जहाँ सभी अनुक्रमित स्तंभ NULL हैं ( उपयोग-the-index-luke.com/sql/where-clause/null/index ) - और एक आभासी स्तंभ decode(status,'ACTIVE',name,null)उदाहरण के लिए हो सकता है ।
जैक डगलस

Thnx, मुझे लगा कि हाल के संस्करणों में बदलाव आया था (और नल इंडेक्स किए गए थे)।
ypercube y 20
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.