# 1071 - निर्दिष्ट कुंजी बहुत लंबी थी; अधिकतम कुंजी लंबाई 1000 बाइट्स है


102

मुझे पता है कि इस शीर्षक के साथ सवाल पहले जवाब दिए गए हैं, लेकिन कृपया इसे पढ़ें। मैंने पोस्ट करने से पहले इस त्रुटि पर अन्य सभी प्रश्नों / उत्तरों को अच्छी तरह से पढ़ा है।

मुझे निम्नलिखित प्रश्न के लिए उपरोक्त त्रुटि मिल रही है:

CREATE TABLE IF NOT EXISTS `pds_core_menu_items` (
  `menu_id` varchar(32) NOT NULL,
  `parent_menu_id` int(32) unsigned DEFAULT NULL,
  `menu_name` varchar(255) DEFAULT NULL,
  `menu_link` varchar(255) DEFAULT NULL,
  `plugin` varchar(255) DEFAULT NULL,
  `menu_type` int(1) DEFAULT NULL,
  `extend` varchar(255) DEFAULT NULL,
  `new_window` int(1) DEFAULT NULL,
  `rank` int(100) DEFAULT NULL,
  `hide` int(1) DEFAULT NULL,
  `template_id` int(32) unsigned DEFAULT NULL,
  `alias` varchar(255) DEFAULT NULL,
  `layout` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`menu_id`),
  KEY `index` (`parent_menu_id`,`menu_link`,`plugin`,`alias`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

क्या किसी को यह पता है कि इसे क्यों और कैसे ठीक करना है? पकड़ है - यह वही क्वेरी मेरे स्थानीय मशीन पर पूरी तरह से काम करती है, और मेरे पिछले होस्ट पर भी काम करती है। Btw.it एक परिपक्व परियोजना से - phpdevshell - तो मुझे लगता है कि ये लोग जानते हैं कि वे क्या कर रहे हैं, हालांकि आप कभी नहीं जानते हैं।

किसी भी सुराग की सराहना की।

मैं phpMyAdmin का उपयोग कर रहा हूं।

जवाबों:


170

जैसा कि @Dartart कहता है, आपके सूचकांक की कुल लंबाई बहुत लंबी है।

संक्षिप्त उत्तर यह है कि आपको ऐसे लंबे VARCHAR कॉलमों को वैसे भी अनुक्रमित नहीं किया जाना चाहिए, क्योंकि सूचकांक बहुत भारी और अक्षम होगा।

सबसे अच्छा अभ्यास उपसर्ग अनुक्रमित का उपयोग करना है ताकि आप केवल डेटा के बाएं विकल्प को अनुक्रमित कर रहे हैं। आपके अधिकांश डेटा वैसे भी 255 वर्णों से बहुत कम होंगे।

आप सूचकांक को परिभाषित करते हुए प्रति कॉलम एक उपसर्ग लंबाई घोषित कर सकते हैं। उदाहरण के लिए:

...
KEY `index` (`parent_menu_id`,`menu_link`(50),`plugin`(50),`alias`(50))
...

लेकिन किसी दिए गए कॉलम के लिए सबसे अच्छी उपसर्ग लंबाई क्या है? यह पता लगाने की एक विधि है:

SELECT
 ROUND(SUM(LENGTH(`menu_link`)<10)*100/COUNT(`menu_link`),2) AS pct_length_10,
 ROUND(SUM(LENGTH(`menu_link`)<20)*100/COUNT(`menu_link`),2) AS pct_length_20,
 ROUND(SUM(LENGTH(`menu_link`)<50)*100/COUNT(`menu_link`),2) AS pct_length_50,
 ROUND(SUM(LENGTH(`menu_link`)<100)*100/COUNT(`menu_link`),2) AS pct_length_100
FROM `pds_core_menu_items`;

यह आपको उन पंक्तियों के अनुपात को बताता है जिनके menu_linkकॉलम में दी गई स्ट्रिंग लंबाई से अधिक नहीं है । आप इस तरह से आउटपुट देख सकते हैं:

+---------------+---------------+---------------+----------------+
| pct_length_10 | pct_length_20 | pct_length_50 | pct_length_100 |
+---------------+---------------+---------------+----------------+
|         21.78 |         80.20 |        100.00 |         100.00 |
+---------------+---------------+---------------+----------------+

यह बताता है कि आपके 80% तार 20 वर्णों से कम हैं, और आपके सभी तार 50 वर्णों से कम हैं। इसलिए 50 की उपसर्ग लंबाई से अधिक अनुक्रमित करने की आवश्यकता नहीं है, और निश्चित रूप से 255 वर्णों की पूरी लंबाई को अनुक्रमित करने की आवश्यकता नहीं है।

पुनश्च: INT(1)और INT(32)डेटा प्रकार MySQL के बारे में एक और गलतफहमी को इंगित करता है। संख्यात्मक तर्क में स्टोरेज या कॉलम के लिए अनुमत मूल्यों की श्रेणी से संबंधित कोई प्रभाव नहीं है। INTहमेशा 4 बाइट्स होता है, और यह हमेशा -2147483648 से 2147483647 तक मूल्यों की अनुमति देता है। संख्यात्मक तर्क प्रदर्शन के दौरान पैडिंग मूल्यों के बारे में है, जिसका कोई प्रभाव नहीं है जब तक कि आप ZEROFILLविकल्प का उपयोग नहीं करते हैं ।


17
विस्तृत विवरण के लिए बहुत बहुत धन्यवाद। एक समस्या को ठीक करने के अलावा, मैंने कुछ मूल्यवान भी सीखा है।
कोडविर्टोसो

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

1
आपके काम की क्वेरी में एक सूक्ष्म बग है यह मापने के लिए कि तार कितने लंबे हैं: आप मान रहे हैं कि तार सभी मौजूद हैं; यह है, कि वे सब वहाँ हैं। यदि कुछ अशक्त हैं, तो यह आपकी गणना को समाप्त कर देगा और छोटे तारों को कम कर देगा। आप गिनती (*) के बजाय गिनती ([field_name]) का उपयोग करना चाहते हैं।
डी मैक

यह पहले "उपसर्ग" सूचकांक से अधिक का उपयोग नहीं करेगा।
रिक जेम्स

28

इस त्रुटि का मतलब है कि सूचकांक की लंबाई indexअधिक है तो 1000 बाइट्स। MySQL और स्टोरेज इंजन में यह प्रतिबंध हो सकता है। मुझे MySQL 5.5 पर समान त्रुटि मिली है - 'निर्दिष्ट कुंजी बहुत लंबी थी; इस स्क्रिप्ट को चलाने पर अधिकतम कुंजी की लंबाई 3072 बाइट्स है:

CREATE TABLE IF NOT EXISTS test_table1 (
  column1 varchar(500) NOT NULL,
  column2 varchar(500) NOT NULL,
  column3 varchar(500) NOT NULL,
  column4 varchar(500) NOT NULL,
  column5 varchar(500) NOT NULL,
  column6 varchar(500) NOT NULL,
  KEY `index` (column1, column2, column3, column4, column5, column6)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

UTF8 मल्टी-बाइट्स है, और कुंजी लंबाई की गणना इस तरह से की जाती है - 500 * 3 * 6 = 9000 बाइट्स।

लेकिन ध्यान दें, अगली क्वेरी काम करती है!

CREATE TABLE IF NOT EXISTS test_table1 (
  column1 varchar(500) NOT NULL,
  column2 varchar(500) NOT NULL,
  column3 varchar(500) NOT NULL,
  column4 varchar(500) NOT NULL,
  column5 varchar(500) NOT NULL,
  column6 varchar(500) NOT NULL,
  KEY `index` (column1, column2, column3, column4, column5, column6)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

... क्योंकि मैंने CHARSET = latin1 का उपयोग किया, इस मामले में कुंजी की लंबाई 500 * 6 = 3000 बाइट्स है।


7
उत्तर के लिए धन्यवाद, यह काम करता है, लेकिन utf8 charset को छोड़ने की कीमत पर। क्या इस प्रतिबंध को किसी तरह दूर किया जा सकता है (मेरे पास पूर्ण सर्वर एक्सेस है), क्या यह एक अच्छे कारण के लिए है?
संहिताविषु

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

16

मेरे पास यह मुद्दा था, और निम्नलिखित द्वारा हल किया गया:

कारण

MyISAM से संबंधित MySQL के साथ एक ज्ञात बग है, UTF8 वर्ण सेट और इंडेक्स हैं जिन्हें आप यहां देख सकते हैं।

संकल्प

  • सुनिश्चित करें कि MySQL InnoDB स्टोरेज इंजन के साथ कॉन्फ़िगर किया गया है।

  • डिफ़ॉल्ट रूप से उपयोग किए जाने वाले स्टोरेज इंजन को बदलें ताकि नए टेबल हमेशा उचित रूप से बनाए जाएं:

    set GLOBAL storage_engine='InnoDb';

  • MySQL 5.6 और बाद के लिए, निम्नलिखित का उपयोग करें:

    SET GLOBAL default_storage_engine = 'InnoDB';

  • और अंत में सुनिश्चित करें कि आप माइग्रेट करने के लिए MySQL में दिए गए निर्देशों का पालन कर रहे हैं ।

संदर्भ


ज्यादातर मामलों में, हम भंडारण इंजन को 'InnoDB' के रूप में कॉन्फ़िगर करना भूल जाते हैं। निम्नलिखित उत्तर सबसे सरल है और संभवत: यहां अधिकांश उपयोगकर्ताओं के लिए समस्या का समाधान होगा। धन्यवाद।
फ्रेडेरिको सेसर

10

तालिका बनाने या बदलने से पहले इस क्वेरी को चलाएँ।

SET @@global.innodb_large_prefix = 1;

यह अधिकतम मुख्य लंबाई 3072 बाइट्स के लिए सेट करेगा


3

यह सूचकांक आकार सीमा MySQL के 64 बिट बिल्ड पर बड़ी लगती है।

मैं इस सीमा को मार रहा था, जो हमारे देव डेटाबेस को डंप करने की कोशिश कर रहा था और इसे स्थानीय वीएमवेयर पुण्य पर लोड कर रहा था। अंत में मुझे महसूस हुआ कि दूरस्थ देव सर्वर 64 बिट था और मैंने 32 बिट पुण्य बनाया था। मैंने सिर्फ 64 बिट पुण्य बनाया और मैं स्थानीय रूप से डेटाबेस लोड करने में सक्षम था।


2

मैंने मूल डेटाबेस में "लंबाई" के मानों को बदलकर इस त्रुटि को बाईपास कर दिया है, इसकी संरचना को बदलकर लगभग "1000" के कुल डेटाबेस में, और फिर उसी को निर्यात करके, सर्वर को। :)


0

मैं एक ही मुद्दे का सामना कर रहा था, इसे हल करने के लिए क्वेरी के नीचे उपयोग किया गया था।

DB बनाते समय आप utf-8 एन्कोडिंग का उपयोग कर सकते हैं

जैसे। create database my_db character set utf8 collate utf8mb4;

संपादित करें: (टिप्पणियों से सुझावों को ध्यान में रखते हुए) utf8mb4 को utf8mb4 में बदल दिया


2
इसने मुझे सही दिशा में इशारा किया। मेरे लिए मुझे अपने टकराव को बदलना पड़ा: utf8_general_ci
Ian Newland

2
यह सही दिशा नहीं है, यह मत करो! MySQL utf8नहीं है utf8, यह एक खराब स्वामित्व वाला प्रारूप है जिसे कभी नहीं आना चाहिए। utf8mb4सही है utf8और उचित utf8समर्थन के लिए अनुशंसित डिफ़ॉल्ट है ।
जेफ्री

utf8mb4सही एन्कोडिंग नहीं mysql पर उपयोग करने के लिए और हैutf8
आलोक

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