In der Produktionsumgebung gibt es häufig einige implizite Typkonvertierungen, die dazu führen, dass SQL-Indizes fehlschlagen und eine extrem schlechte Leistung erbringen, was sich wiederum auf die Clusterlast und das Geschäft auswirkt. In diesem Artikel werden häufige Szenarien der impliziten Konvertierung zusammengefasst. Versuchen Sie, die implizite SQL-Konvertierung in der Produktion zu vermeiden.
Autor: Zhang Luodan interessiert sich leidenschaftlich für Datenbanktechnologie und erforscht sie ständig. Er hofft, in Zukunft ausführlichere Artikel schreiben und wertvollere Inhalte veröffentlichen zu können!
Produziert von der Aikeson Open Source Community. Bitte kontaktieren Sie den Herausgeber und geben Sie die Quelle für den Nachdruck an.
Dieser Artikel umfasst etwa 3.000 Wörter und die Lektüre dauert voraussichtlich 10 Minuten.
Zu den häufigsten Szenarios, in denen SQL implizite Konvertierungen generiert, gehören:
- Implizite Konvertierung von Datentypen
- Implizite Konvertierung von Zeichensätzen
Dabei wird die Zeichensatzkonvertierung, insbesondere in Tabellenverbindungsszenarien und gespeicherten Prozeduren, leicht übersehen.
Hinweis: Der Zeichensatz ist die Kodierungsregel für Zeichentypdaten. Für numerische Typen ist keine Konvertierung des Zeichensatzes erforderlich.
Implizite Konvertierung von Datentypen
Testtabellenstruktur
t1
Die Tabellenfelder a
sind vom Typ VARCHAR und t2
die Tabellenfelder a
vom Typ INT.
mysql> show create database test1\G
*************************** 1. row ***************************
Database: test1
Create Database: CREATE DATABASE `test1` /*!40100 DEFAULT CHARACTER SET utf8 */
1 row in set (0.00 sec)
mysql> show create table t1\G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`id` int(11) NOT NULL,
`a` varchar(20) DEFAULT NULL,
`b` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `a` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
mysql> show create table t2\G
*************************** 1. row ***************************
Table: t2
Create Table: CREATE TABLE `t2` (
`id` int(11) NOT NULL,
`a` int(11) DEFAULT NULL,
`b` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `a` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
Beispiel für eine einzelne Tabelle
Hierbei ist zu beachten, dass es die folgenden zwei Arten von Konvertierungen gibt:
- Wenn der Feldtyp ein Zeichenfolgentyp und der Parameter eine Ganzzahl ist, schlägt der Index fehl.
- Wenn der Feldtyp eine Ganzzahl und der eingehende Parameter ein Zeichenfolgentyp ist, führt dies nicht zu einem Indexfehler.
Dies liegt daran, dass MySQL beim Vergleich von Zeichenfolgen und Zahlen den Zeichenfolgentyp zum Vergleich in eine Zahl umwandelt. Wenn der Feldtyp eine Zeichenfolge ist, wird dem Feld daher eine Funktion hinzugefügt, was dazu führt, dass der Index fehlschlägt.
In der offiziellen Dokumentation wird erklärt : Zeichenfolgen werden bei Bedarf automatisch in Zahlen und Zahlen in Zeichenfolgen umgewandelt.
-- 字段类型为varchar,传参为整数,无法走到索引
mysql> explain select * from t1 where a=1000;
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| 1 | SIMPLE | t1 | NULL | ALL | a | NULL | NULL | NULL | 498892 | 10.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+
1 row in set, 3 warnings (0.00 sec)
mysql> show warnings;
+---------+------+---------------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------------------------------------------------------------------------------------------------------------------+
| Warning | 1739 | Cannot use ref access on index 'a' due to type or collation conversion on field 'a' |
| Warning | 1739 | Cannot use range access on index 'a' due to type or collation conversion on field 'a' |
| Note | 1003 | /* select#1 */ select `test1`.`t1`.`id` AS `id`,`test1`.`t1`.`a` AS `a`,`test1`.`t1`.`b` AS `b` from `test1`.`t1` where (`test1`.`t1`.`a` = 1000) |
+---------+------+---------------------------------------------------------------------------------------------------------------------------------------------------+
3 rows in set (0.00 sec)
-- 字段类型为int,传参为字符串,可以走到索引
mysql> explain select * from t2 where a='1000';
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+
| 1 | SIMPLE | t2 | NULL | ref | a | a | 5 | const | 1 | 100.00 | NULL |
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)
Warum können Sie Zahlen zum Vergleich nicht in Zeichenfolgen umwandeln?
Vergleichsergebnisse unten:
- Beim Vergleich von Zeichenfolgen wird die Größe der Zeichenfolge einzeln verglichen, bis unterschiedliche Zeichen gefunden werden. Die Vergleichsergebnisse dieses Vergleichs unterscheiden sich von den Vergleichsergebnissen von Zahlen.
mysql> select '2000' <'250';
+---------------+
| '2000' <'250' |
+---------------+
| 1 |
+---------------+
1 row in set (0.00 sec)
Datentypkonvertierung in Tabellenverknüpfungen
Wenn die Verbindungsfeldtypen der beiden Tabellen inkonsistent sind, führt dies zu einer impliziten Konvertierung (eine interne MySQL- cast()
Funktion wird hinzugefügt), der Verbindungsfeldindex kann nicht erreicht werden und die optimale Tabellenverbindungsreihenfolge wird möglicherweise nicht verwendet.
Die Tabelle, die ursprünglich eine getriebene Tabelle war, kann als treibende Tabelle verwendet werden, da der Index nicht verwendet werden kann.
Beispiel:
- Unter normalen Umständen
t2
wird die Tabelle wie folgt als treibende Tabelle ausgewählt. Aufgrund unterschiedlicher Datentypen lautet die tatsächliche SQL-Ausführung jedoch wie folgt:select * from t1 join t2 on cast(t1.a as unsigned)=t2.a where t2.id<1000
- Bei
t1
Verwendung als gesteuerte Tabelle gibt es keine Möglichkeit, zumt1.a
Index von zu wechseln, dahert1
wird die Tabelle als steuernde Tabelle ausgewählt
mysql> explain select * from t1 join t2 on t1.a=t2.a where t2.id<1000;
+----+-------------+-------+------------+------+---------------+------+---------+------------+--------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------------+--------+----------+-----------------------+
| 1 | SIMPLE | t1 | NULL | ALL | a | NULL | NULL | NULL | 498892 | 100.00 | Using where |
| 1 | SIMPLE | t2 | NULL | ref | PRIMARY,a | a | 5 | test1.t1.a | 1 | 5.00 | Using index condition |
+----+-------------+-------+------------+------+---------------+------+---------+------------+--------+----------+-----------------------+
2 rows in set, 2 warnings (0.00 sec)
mysql> show warnings;
+---------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Warning | 1739 | Cannot use ref access on index 'a' due to type or collation conversion on field 'a' |
| Note | 1003 | /* select#1 */ select `test1`.`t1`.`id` AS `id`,`test1`.`t1`.`a` AS `a`,`test1`.`t1`.`b` AS `b`,`test1`.`t2`.`id` AS `id`,`test1`.`t2`.`a` AS `a`,`test1`.`t2`.`b` AS `b` from `test1`.`t1` join `test1`.`t2` where ((`test1`.`t2`.`id` < 1000) and (`test1`.`t1`.`a` = `test1`.`t2`.`a`)) |
+---------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.01 sec)
Implizite Konvertierung von Zeichensätzen
Wenn der Parameterzeichensatz und der Feldzeichensatz unterschiedlich sind, kann kein direkter Vergleich durchgeführt werden und es ist eine Zeichensatzkonvertierung erforderlich. Möglicherweise müssen Sie convert()
dem Konvertierungsfeld eine Funktion hinzufügen, um den Zeichensatz zu konvertieren, was zu einem Indexfehler führt.
Testtabellenstruktur
- Der Datenbankzeichensatz ist UTF8MB4
t1
Der Tabellenzeichensatz ist UTF8t2
Der Tabellenzeichensatz ist UTF8MB4
mysql> show create database test\G
*************************** 1. row ***************************
Database: test
Create Database: CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER SET utf8mb4 */
mysql> show create table t1\G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`id` int(11) NOT NULL,
`a` varchar(20) DEFAULT NULL,
`b` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `a` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
mysql> show create table t2\G
*************************** 1. row ***************************
Table: t2
Create Table: CREATE TABLE `t2` (
`id` int(11) NOT NULL,
`a` varchar(20) DEFAULT NULL,
`b` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `a` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
1 row in set (0.01 sec)
Beispiel für eine einzelne Tabelle
-- 正常执行时,匹配字段的字符集(没有单独指定时继承表的字符集)
mysql> explain select * from t1 where a='1000';
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+
| 1 | SIMPLE | t1 | NULL | ref | a | a | 63 | const | 1 | 100.00 | NULL |
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)
-- 将参数转换不同的字符集,无法走到索引,而是全表扫描
mysql> explain select * from t1 where a=convert('1000' using utf8mb4);
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 2000 | 100.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
-- show warnings可以看到优化器进行了转换,在t1.a上加了convert函数,从而无法走到索引
mysql> show warnings;
+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message |
+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Note | 1003 | /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where (convert(`test`.`t1`.`a` using utf8mb4) = <cache>(convert('1000' using utf8mb4))) |
+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
Darüber hinaus ist zu beachten:
MySQL räumt intern der Konvertierung von Zeichensätzen niedriger Ebene in Zeichensätze höherer Ebene Priorität ein, beispielsweise der Konvertierung von UTF8 in UTF8MB4.
Im vorherigen Beispiel convert()
wurde die Funktion t1.a
zu hinzugefügt, im folgenden Beispiel convert()
wurde die Funktion jedoch zum Parameter anstelle t2.a
des Felds hinzugefügt. Diese Situation führte nicht zu einer schlechten Leistung:
mysql> show create table t2\G
*************************** 1. row ***************************
Table: t2
Create Table: CREATE TABLE `t2` (
`id` int(11) NOT NULL,
`a` varchar(20) DEFAULT NULL,
`b` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `a` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
1 row in set (0.00 sec)
mysql> explain select * from t2 where a=convert('1000' using utf8);
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+
| 1 | SIMPLE | t2 | NULL | ref | a | a | 83 | const | 1 | 100.00 | NULL |
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)
mysql> show warnings;
+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message |
+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Note | 1003 | /* select#1 */ select `test`.`t2`.`id` AS `id`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where (`test`.`t2`.`a` = convert(convert('1000' using utf8) using utf8mb4)) |
+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
Um zusammenzufassen:
- Wenn der Zeichensatz des Tabellenfelds ein Zeichensatz niedrigerer Ebene (z. B. UTF8) ist und der eingehende Wert ein Zeichensatz höherer Ebene (z. B. UTF8MB4) ist, wird der Zeichensatz des Tabellenfelds zu diesem Zeitpunkt konvertiert. Dies entspricht der Verwendung der Funktion, Index ungültig.
- Wenn das Tabellenfeld ein Zeichensatz höherer Ebene (z. B. UTF8MB4) und der eingehende Wert ein Zeichensatz niedrigerer Ebene (z. B. UTF8) ist, wird der eingehende Wert in den Zeichensatz konvertiert und verursacht keinen Indexfehler. .
Normalerweise verwenden wir convert()
die Funktion jedoch nicht zum manuellen Konvertieren des Zeichensatzes von Parametern. In den folgenden beiden Szenarien kann es zu impliziten Typkonvertierungen kommen, die leicht zu ignorieren sind und zu Produktionsproblemen führen.
Zeichensatzkonvertierung in Tabellenverknüpfungen
Wenn die Zeichensätze der Verbindungsfelder der beiden Tabellen inkonsistent sind, führt dies zu einer impliziten Konvertierung ( convert()
in MySQL hinzugefügte Funktion), und der Verbindungsfeldindex kann nicht erreicht werden und die optimale Tabellenverbindungssequenz wird möglicherweise nicht verwendet.
Die Tabelle, die ursprünglich eine getriebene Tabelle war, kann als treibende Tabelle verwendet werden, da der Index nicht verwendet werden kann.
Beispiel:
- Unter normalen Umständen gibt MySQL Tabellen mit kleinen Ergebnismengen als treibende Tabellen den Vorrang. In diesem Beispiel handelt es sich um
t2
die treibende Tabelle undt1
die getriebene Tabelle. - Aufgrund der unterschiedlichen Zeichensätze ist das tatsächlich ausgeführte SQL jedoch wie in der Abbildung
show warnings
dargestellt . Wennt1.a
dem Feld eine Funktionconvert()
zum Konvertieren des Zeichensatzes hinzugefügt wird,t1.a
kann der Index des Feldes nicht erreicht werden und die Verbindungsreihenfolge muss geändert werden .
mysql> explain select * from t1 left join t2 on t1.a=t2.a where t2.id<1000;
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-----------------------+
| 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 498649 | 100.00 | NULL |
| 1 | SIMPLE | t2 | NULL | ref | PRIMARY,a | a | 83 | func | 1 | 4.79 | Using index condition |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-----------------------+
2 rows in set, 1 warning (0.00 sec)
mysql> show warnings;
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message |
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Note | 1003 | /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`id` AS `id`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`id` < 1000) and (convert(`test`.`t1`.`a` using utf8mb4) = `test`.`t2`.`a`)) |
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
-- 在下面示例中,虽然也发生了类型转换,但是效率并没有变差,因为原本最优的连接顺序就是t1作为驱动表
mysql> explain select * from t1 left join t2 on t1.a=t2.a where t1.id<1000;
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| 1 | SIMPLE | t1 | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 999 | 100.00 | Using where |
| 1 | SIMPLE | t2 | NULL | ref | a | a | 83 | func | 1 | 100.00 | Using where |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)
mysql> show warnings;
+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message |
+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Note | 1003 | /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`id` AS `id`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` left join `test`.`t2` on((convert(`test`.`t1`.`a` using utf8mb4) = `test`.`t2`.`a`)) where (`test`.`t1`.`id` < 1000) |
+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
Zeichensatzkonvertierung in gespeicherten Prozeduren
Dies ist auch ein Szenario, das relativ leicht zu ignorieren ist. Das Problem wurde entdeckt, als der Primärschlüssel während des Speichervorgangs in der Produktionsumgebung aktualisiert wurde, die Ausführung jedoch mehr als 10 Sekunden dauerte.
Der Zeichensatz der Variablen in der gespeicherten Prozedur wird vom database
Zeichensatz von (kann auch beim Erstellen angegeben werden) verwendet. Wenn sich der Zeichensatz des Tabellenfelds database
vom Zeichensatz von () unterscheidet, erfolgt eine implizite Zeichensatztypkonvertierung ähnlich der vorherigen einer wird passieren.
Beispiel:
database
Der Zeichensatz ist UTF8MB4character_set_client
und sind die Werte der Sitzung undcollation_connection
beim Erstellen der gespeicherten Prozedurcharacter_set_client
collation_connection
- Es wurde getestet, dass der Zeichensatz der Variablen in der gespeicherten Prozedur mit dem Zeichensatz auf Datenbankebene übereinstimmt.
-- 存储过程信息: Database Collation: utf8mb4_general_ci
mysql> show create procedure update_data\G
*************************** 1. row ***************************
Procedure: update_data
sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
Create Procedure: CREATE DEFINER=`root`@`%` PROCEDURE `update_data`()
begin
declare j int;
declare n varchar(100);
select charset(n);
set j=1;
while(j<=2000)do
set n = cast(j as char);
select 1,now();
update t1 set b=concat(b,'1') where a=n;
select 2,now();
select sleep(1);
set j=j+1;
end while;
end
character_set_client: utf8mb4
collation_connection: utf8mb4_general_ci
Database Collation: utf8mb4_general_ci
1 row in set (0.00 sec)
如下,在执行存储过程后,看到打印的变量n的字符集是utf8mb4
mysql> call update_data();
+------------+
| charset(n) |
+------------+
| utf8mb4 |
+------------+
1 row in set (0.00 sec)
Die auf der Grundlage des Indexfelds aktualisierte Anweisung a
sieht unter Verwendung eines vollständigen Tabellenscans (Typ: Index, Schlüssel: Primär) tatsächlich wie folgt aus.
mysql> explain update t1 set b=concat(b,'1') where a=convert('1000' using utf8mb4);
+----+-------------+-------+------------+-------+---------------+---------+---------+------+--------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+--------+----------+-------------+
| 1 | UPDATE | t1 | NULL | index | NULL | PRIMARY | 4 | NULL | 498649 | 100.00 | Using where |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+--------+----------+-------------+
1 row in set (0.00 sec)
-- 而正常情况下,执行计划为:
mysql> explain update t1 set b=concat(b,'1') where a='1000';
+----+-------------+-------+------------+-------+---------------+------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+------+---------+-------+------+----------+-------------+
| 1 | UPDATE | t1 | NULL | range | a | a | 63 | const | 1 | 100.00 | Using where |
+----+-------------+-------+------------+-------+---------------+------+---------+-------+------+----------+-------------+
1 row in set (0.00 sec)
Die Aktualisierungszeit wurde ebenfalls von 0,00 Sek. auf 0,60 Sek. geändert . Wenn die Menge an Tabellendaten groß ist, hat ein vollständiger Tabellenscan größere Auswirkungen auf die Produktion.
mysql> update t1 set b=concat(b,'1') where a='1000';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update t1 set b=concat(b,'1') where a=convert('1000' using utf8mb4);
Query OK, 1 row affected (0.60 sec)
Rows matched: 1 Changed: 1 Warnings: 0
So vermeiden Sie implizite Konvertierungen
Für die implizite Konvertierung von Datentypen:
- Auswahl des Standarddatentyps
- SQL-Übergabe der Datentypübereinstimmung der beteiligten Felder
Bei der impliziten Konvertierung von Zeichensätzen bleiben Client-Zeichensatz, serverseitiger Zeichensatz, Datenbank-Zeichensatz, Tabellen-Zeichensatz und Feld-Zeichensatz konsistent.
Weitere technische Artikel finden Sie unter: https://opensource.actionsky.com/
Über SQLE
SQLE ist eine umfassende SQL-Qualitätsmanagementplattform, die die SQL-Prüfung und -Verwaltung von der Entwicklung bis zur Produktionsumgebung abdeckt. Es unterstützt gängige Open-Source-, kommerzielle und inländische Datenbanken, bietet Prozessautomatisierungsfunktionen für Entwicklung, Betrieb und Wartung, verbessert die Online-Effizienz und verbessert die Datenqualität.
SQLE erhalten
Typ | Adresse |
---|---|
Repository | https://github.com/actiontech/sqle |
dokumentieren | https://actiontech.github.io/sqle-docs/ |
Neuigkeiten veröffentlichen | https://github.com/actiontech/sqle/releases |
Entwicklungsdokumentation für das Datenaudit-Plug-in | https://actiontech.github.io/sqle-docs/docs/dev-manual/plugins/howtouse |