MySQL के पास MyISAM या InnoDB पर hash सूचकांक क्यों नहीं है?


35

मेरे पास एक एप्लिकेशन है जो केवल समानता पर चयन करेगा, और मुझे लगता है कि मुझे btree सूचकांक पर हैश इंडेक्स का उपयोग करना चाहिए। मेरे निराशा, हैश सूचकांकों में से अधिकांश MyISAM या InnoDB पर समर्थित नहीं हैं। उसके साथ क्या है?


2
Mysql भी फंक्शन-आधारित इंडेक्स, बिटमैप इंडेक्स, इत्यादि का समर्थन नहीं करता है, सिर्फ इसलिए कि यह

1
मुझे लगा कि हैश इंडेक्स तो थे ... मौलिक ... मुझे लगता है कि विशिष्ट कार्यान्वयन-संबंधित कारण है।

1
@ एलेक्स: मुझे यकीन है कि इसका कारण "आलस्य" और "नौकरशाही" है, लेकिन चलो जवाब की प्रतीक्षा करें))


मैंने अपने उत्तर के अंत में उच्च प्रदर्शन MySQL बुक से एक अच्छा एचएसएच एल्गोरिथ्म जोड़ा।
रोलैंडमाइसीडीडीबीए

जवाबों:


16

कई डेटाबेस हैश आधारित अनुक्रमणिका का समर्थन नहीं करते सब पर

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

इसलिए आम तौर पर उपयोगी होने के लिए (यानी आमतौर पर विकल्प से बेहतर) सूचकांक को कभी-कभी फिर से बनाने की आवश्यकता होती है क्योंकि डेटा बढ़ता है (और सिकुड़ता है) जो एक महत्वपूर्ण आंतरायिक ओवरहेड जोड़ सकता है। यह आमतौर पर मेमोरी आधारित तालिकाओं के साथ ठीक है क्योंकि पुनर्निर्माण शायद बहुत तेज होने वाला है (जैसा कि डेटा हमेशा रैम में रहने वाला है और किसी भी मामले में बड़े पैमाने पर होने की संभावना नहीं है), लेकिन डिस्क पर एक बड़े सूचकांक का पुनर्निर्माण करना एक है बहुत भारी ऑपरेशन (और IIRC mySQL लाइव इंडेक्स रीबिल्ड का समर्थन नहीं करता है इसलिए ऑपरेशन के दौरान टेबल लॉक रखता है)।

इसलिए हैश इंडेक्स का उपयोग मेमोरी टेबल में किया जाता है क्योंकि वे आम तौर पर बेहतर प्रदर्शन करने वाले होते हैं, लेकिन डिस्क आधारित टेबल उनका समर्थन नहीं करते हैं क्योंकि वे बोनस नहीं होने के लिए एक बाधा हो सकते हैं। बंद हैश अनुक्रमणिका के लिए कुछ भी निश्चित रूप से डिस्क आधारित तालिकाओं के लिए उपलब्ध कराया जा रहा है, इसमें कोई शक नहीं कुछ डेटाबेसों कर सुविधा का समर्थन है, लेकिन शायद वे ISAM में लागू नहीं कर रहे हैं / देखरेख के रूप में InnoDB टेबल सुविधा लायक जोड़ने (के रूप में विचार नहीं करते लिखने और बनाए रखने के लिए अतिरिक्त कोड उन कुछ परिस्थितियों में लाभ के लायक नहीं है कि यह एक महत्वपूर्ण अंतर बनाता है)। शायद अगर आप दृढ़ता से असहमत हैं तो आप उनसे बात कर सकते हैं और सुविधा के कार्यान्वयन के लिए एक अच्छा मामला बना सकते हैं।

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


क्या पूरी मेज को लॉक किए बिना फिर से हैशिंग (पुनर्निर्माण) करने की अनुमति देने का कोई तरीका है?
पचेरियर

@Pacerier: ऐसा नहीं है कि मुझे MySQL के बारे में पता है (हालाँकि वे फीचर को जोड़ सकते थे क्योंकि मैंने इसका अंतिम बार उपयोग किया था, इसलिए दस्तावेज़ की जाँच करें)। यहां तक ​​कि जहां एक डीबीएमएस ऑनलाइन इंडेक्स निर्माण / पुनर्निर्माण का समर्थन करता है, वह डिफ़ॉल्ट विकल्प नहीं है। जो लॉक किया जाता है वह अलग-अलग होगा: कुछ टेबल पर राइट लॉक लगाएगा, अन्य लेन-देन में देरी नहीं होगी यदि वे केवल पढ़ रहे हैं, तो कुछ डीएमबीएस पूरा टेबल लॉक निकाल लेंगे। यदि आपको ऑनलाइन पुनर्निर्माण की आवश्यकता है , तो उपयोग करने से पहले प्रत्येक DBMS के प्रलेखन की जांच करें।
डेविड स्पिललेट

आमतौर पर पुनर्निर्माण केवल तब आवश्यक है जब डेटा की लंबाई दोगुनी हो। क्या उन्हें वास्तव में हर मिनट डेटा लंबाई दोगुनी होने की चिंता करनी होगी? (आम तौर पर ऐसा बहुत कम ही होता है जब डेटाबेस इस बात के लिए बड़ा होता है कि वह चिंता का विषय हो)
SOFe

6

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

http://www.postgresql.org/docs/8.1/static/indexes-types.html

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

फिर से, यह (अप्रचलित संस्करण) PostgreSQL- विशिष्ट है, लेकिन यह संकेत देना चाहिए कि "प्राकृतिक" सूचकांक प्रकार आवश्यक रूप से इष्टतम प्रदर्शन नहीं करेगा।


5

यहाँ कुछ दिलचस्प है:

पुस्तक MySQL 5.0 प्रमाणन अध्ययन गाइड , पृष्ठ 433, धारा 29.5.1 के अनुसार

मेमोरी इंजन डिफ़ॉल्ट इंडेक्सिंग एल्गोरिथ्म द्वारा एचएएसएच का उपयोग करता है।

हंसने के लिए, मैंने MySQL 5.5.12 में HASH का उपयोग करके एक प्राथमिक कुंजी के साथ एक InnoDB तालिका और एक MyISAM तालिका बनाने की कोशिश की

mysql> use test
Database changed
mysql> create table rolando (num int not null, primary key (num) using hash);
Query OK, 0 rows affected (0.11 sec)

mysql> show create table rolando\G
*************************** 1. row ***************************
       Table: rolando
Create Table: CREATE TABLE `rolando` (
  `num` int(11) NOT NULL,
  PRIMARY KEY (`num`) USING HASH
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

mysql> create table rolando2 (num int not null, primary key (num) using hash) engine=MyISAM;
Query OK, 0 rows affected (0.05 sec)

mysql> show create table rolando2\G
*************************** 1. row ***************************
       Table: rolando2
Create Table: CREATE TABLE `rolando2` (
  `num` int(11) NOT NULL,
  PRIMARY KEY (`num`) USING HASH
) ENGINE=MyISAM DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

MySQL ने शिकायत नहीं की।

अद्यतन करें

बुरी खबर !!! मैंने SHOW INDEXES FROM का उपयोग किया। यह कहते हैं कि सूचकांक BTREE है।

बनाएँ सूचकांक वाक्य रचना MySQL पृष्ठ कहा गया है कि केवल स्मृति और NDB भंडारण इंजन HASH सूचकांक समायोजित कर सकते हैं।

mysql> show indexes from rolando;
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table   | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| rolando |          0 | PRIMARY  |            1 | num         | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)

mysql> show indexes from rolando2;
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table    | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| rolando2 |          0 | PRIMARY  |            1 | num         | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)

mysql> create table rolando3 (num int not null, primary key (num)) ENGINE=MEMORY;
Query OK, 0 rows affected (0.03 sec)

mysql> show create table rolando3\G
*************************** 1. row ***************************
       Table: rolando3
Create Table: CREATE TABLE `rolando3` (
  `num` int(11) NOT NULL,
  PRIMARY KEY (`num`)
) ENGINE=MEMORY DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

mysql> show indexes from rolando3;
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table    | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| rolando3 |          0 | PRIMARY  |            1 | num         | NULL      |           0 |     NULL | NULL   |      | HASH       |         |               |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)

कुछ लोगों ने हैश एल्गोरिथ्म का अनुकरण करने के लिए पुस्तक " हाई परफॉर्मेंस मायक्यूसी: ऑप्टिमाइजेशन, बैकअप, प्रतिकृति और अधिक " के पेज 102-105 में इस विचार का पालन किया

पृष्ठ 105 इस त्वरित और गंदे एल्गोरिथ्म को पसंद करता है जो मुझे पसंद है:

SELECT CONV(RIGHT(MD5('whatever value you want'),16),16,10) AS HASH64;

किसी भी तालिका में इसके लिए एक कॉलम बनाएं और इस मान को अनुक्रमित करें।

कोशिश तो करो !!!


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

@ डेविड स्पिल्ट्ट इसमें मुझे आपसे पूरी तरह सहमत होना है। अन्य अनुक्रमण स्ट्रैटेगियों का भी अध्याय 11 में एक ही पुस्तक में "उच्च प्रदर्शन के लिए अनुक्रमण रणनीतियाँ" का सुझाव दिया गया है। मेरे उत्तर में एक अतिरिक्त वृद्धि के रूप में, पुस्तक में वास्तव में एक क्लस्टर इंडेक्स का उपयोग करने का उल्लेख है जो एक ही संरचना में पंक्ति और बीट्री इंडेक्स को संग्रहीत करता है। यह आपके द्वारा बताए गए कम किए गए काम को गति दे सकता है। दुर्भाग्य से, जिन हुप्स के माध्यम से आपको कूदना है, जिनका आपने अभी उल्लेख किया है वे कुछ अपरिहार्य हैं। फिर भी आपकी टिप्पणी पर मुझसे +1, सर !!! वास्तव में, आपके उत्तर के लिए भी +1।
रोलैंडमाइसीडीडीबीए

@RolandoMySQLDBA क्या आप "कस्टम हैशिंग" के हिस्से पर अधिक विस्तार कर सकते हैं, अंतिम पैराग्राफ ज्यादा सुराग देने के लिए नहीं लगता है ...
Pacerier

2

बीट्री एकल पंक्ति देखने के लिए हैश की तुलना में बहुत धीमी नहीं है। चूँकि BTree बहुत ही कुशल रेंज क्वेश्चन प्रदान करता है, क्यों कि BTree के अलावा किसी और चीज़ से परेशान हों।

MySQL BTree ब्लॉकों को कैशिंग करने का एक बहुत अच्छा काम करता है, इसलिए BTree- आधारित क्वेरी को शायद ही कभी I / O करना पड़ता है, जो किसी भी क्वेरी में सबसे बड़ा समय उपभोक्ता है।

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