कहो मेरे पास एक टेबल है

CREATE TABLE `tab_sample` (
  `id` bigint(20) NOT NULL,
  `something` char(2) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

मैं इसे में बदलना चाहूंगा

CREATE TABLE `tab_sample` (
  `id` bigint(20) NOT NULL,
  `something` char(2) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

परंतु

ALTER TABLE `tab_sample` MODIFY
  id bigint(20) NOT NULL AUTO_INCREMENT;

तालिका बड़ी होने पर हमेशा के लिए ले जाता है, क्योंकि किसी कारण से, MYSQL पूरी चीज़ को फिर से लिखने का निर्णय लेता है (पहले अस्थायी तालिका में कॉपी करना, ...)

इसे करने का कोई बेहतर तरीका है? अंत में, यह वास्तव में केवल id के डिफ़ॉल्ट मान के लिए एक नियम बदलना चाहिए, है ना?

1
Rumburak 12 जिंदा 2019, 23:41

1 उत्तर

सबसे बढ़िया उत्तर

आप परिवर्तन को केवल-मेटाडेटा परिवर्तन होने की अपेक्षा कर रहे हैं, लेकिन ऐसा नहीं होगा।

आप परिवर्तन को एक इनप्लेस परिवर्तन के रूप में करने का अनुरोध करके और अनुरोध को संतुष्ट नहीं होने पर त्रुटि देखकर इसका परीक्षण कर सकते हैं।

mysql> alter table tab_sample modify id bigint not null auto_increment, algorithm=inplace;
ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.

InnoDB के पास ALTER TABLE प्रकारों का एक सीमित सबसेट है जिसे इनप्लेस या मेटाडेटा-ओनली परिवर्तनों के रूप में किया जा सकता है। देखें https://dev.mysql.com /doc/refman/5.6/hi/innodb-online-ddl-operations.html

आप जिस परिवर्तन का अनुरोध कर रहे हैं, वह संभवतः "कॉलम डेटा प्रकार बदलना" के रूप में गिना जाता है, भले ही आप प्रकार नहीं बदल रहे हों, लेकिन केवल AUTO_INCREMENT विकल्प बदल रहे हों।


मुझे लगता है कि जब आपके id कॉलम में NULL या 0 होता है, तो MySQL को एज केस के लिए टेबल-कॉपी करनी चाहिए। उस स्थिति में, MySQL एक नया ऑटो-इंक्रीमेंट वैल्यू जेनरेट करेगा और NULL या 0 को बदल देगा।

mysql> insert into tab_sample (id) values (10),(20),(30),(0)

mysql> ALTER TABLE `tab_sample` MODIFY   id bigint(20) NOT NULL AUTO_INCREMENT;
Query OK, 4 rows affected (0.06 sec)

mysql> select * from tab_sample;
+----+-----------+
| id | something |
+----+-----------+
|  1 | NULL      |
| 10 | NULL      |
| 20 | NULL      |
| 30 | NULL      |
+----+-----------+

देखें मेरा 0 ऑटो-इन्क्रीमेंट द्वारा 1 में बदल गया है।

अन्य किनारे का मामला: कॉलम एक अद्वितीय कुंजी नहीं हो सकता है, इसलिए इसमें 0 या न्यूल के साथ कई पंक्तियां हो सकती हैं, और उन सभी को नई आईडी दी जाएगी।

mysql> create table tab_sample2 ( id bigint, key(id));
Query OK, 0 rows affected (0.04 sec)

mysql> insert into tab_sample2 values (10),(20),(30),(0),(0),(0),(NULL),(NULL),(NULL);
Query OK, 9 rows affected (0.02 sec)
Records: 9  Duplicates: 0  Warnings: 0

mysql> alter table tab_sample2 modify column id bigint auto_increment;
Query OK, 9 rows affected (0.06 sec)
Records: 9  Duplicates: 0  Warnings: 0

mysql> select * from tab_sample2;
+----+
| id |
+----+
| 10 |
| 20 |
| 30 |
| 31 |
| 32 |
| 33 |
| 34 |
| 35 |
| 36 |
+----+

MySQL नहीं जानता कि तालिका में कितनी पंक्तियों को नए आईडी मानों की आवश्यकता होगी। यह तालिका की प्रत्येक पंक्ति हो सकती है। तो सुरक्षित होने के लिए, यह केवल एक टेबल-कॉपी करेगा और आवश्यकतानुसार कई पंक्तियों पर ऑटो-इंक मानों को भर देगा।

1
Bill Karwin 13 जिंदा 2019, 00:38