MySQL 里字段的属性很多的,对性能来说,影响也是可大可小的,技术社群的这篇文章《第03期:列非空与自增》就对列的非空和自增属性进行了探究,值得我们学习。
NULL值相关的历史文章如下所示,
关于 NULL 的特性如下,
mysql> show create table t1\G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`r1` varchar(10) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
mysql> show create table t2\G
*************************** 1. row ***************************
Table: t2
Create Table: CREATE TABLE `t2` (
`r1` varchar(10) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
mysql> create table t3 like t1;
Query OK, 0 rows affected (0.04 sec)
mysql> insert into t3 select concat(r1,'database') from t1 limit 2;
Query OK, 2 rows affected (0.02 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from t3;
+------+
| r1 |
+------+
| NULL |
| NULL |
+------+
2 rows in set (0.00 sec)
mysql> insert into t3 select concat(ifnull(r1,''),'database') from t1 limit 2;
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from t3;
+----------+
| r1 |
+----------+
| database |
| database |
+----------+
2 rows in set (0.00 sec)
t1 和 t2 的记录数是一样的,但是字段 r1 包含了 NULL,这导致结果忽略了这些值。
mysql> select count(r1) as rc from t1;
+-------+
| rc |
+-------+
| 16390 |
+-------+
1 row in set (0.01 sec)
mysql> select count(r1) as rc from t2;
+-------+
| rc |
+-------+
| 32768 |
+-------+
1 row in set (0.03 sec)
mysql> select count(ifnull(r1,'')) as rc from t1;
+-------+
| rc |
+-------+
| 32768 |
+-------+
1 row in set (0.03 sec)
mysql> select count(*) as rc from t1;
+-------+
| rc |
+-------+
| 32768 |
+-------+
1 row in set (0.02 sec)
3. 包含 NULL 的索引列
mysql> pager grep -i 'key_len'
PAGER set to 'grep -i 'key_len''
mysql> explain select * from t1 where r1 = ''\G
key_len: 43
1 row in set, 1 warning (0.00 sec)
mysql> explain select * from t2 where r1 = ''\G
key_len: 42
1 row in set, 1 warning (0.00 sec)
4. 各存储引擎相关的对 NULL 的处理
1. 控制自增属性性能的变量:innodb_autoinc_lock_mode
innodb_autoinc_lock_mode=0
innodb_autoinc_lock_mode=1
-- SQL 1
mysql> insert into f1(c2) select rpad(uuid(),100,uuid()) from t1;
Query OK, 16777216 rows affected (3 min 35.92 sec)
Records: 16777216 Duplicates: 0 Warnings: 0
-- SQL 2
mysql> insert into f1(c2) select 'database';
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
innodb_autoinc_lock_mode=2
-- SQL 1
mysql> insert into f1(c2) select rpad(uuid(),100,uuid()) from t1;
Query OK, 16777216 rows affected (3 min 35.92 sec)
Records: 16777216 Duplicates: 0 Warnings: 0
-- SQL 2
mysql> insert into f1(c2) select 'sql2';
Query OK, 1 row affected (0.02 sec)
Records: 1 Duplicates: 0 Warnings: 0
2. 控制自增属性的步长以及偏移量
auto_increment_increment 控制步长 auto_increment_offset 控制偏移量
3. 对于要立刻获取插入值的需求
-- SQL 1
mysql> insert into f1(c2) values ('xx1'),('xx2'),('xx3');
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
-- SQL 2
mysql> select last_insert_id() as last_insert_id;
+----------------+
| last_insert_id |
+----------------+
| 1 |
+----------------+
1 row in set (0.00 sec)
-- SQL 3
mysql> select max(c1) as last_insert_id from f1;
+----------------+
| last_insert_id |
+----------------+
| 3 |
+----------------+
1 row in set (0.00 sec)
-- SQL 4
mysql> select * from f1;
+----+------+
| c1 | c2 |
+----+------+
| 1 | xx1 |
| 2 | xx2 |
| 3 | xx3 |
+----+------+
3 rows in set (0.00 sec)
4. 自增列溢出现象
mysql> drop table f1;
Query OK, 0 rows affected (0.04 sec)
mysql> create table f1(c1 tinyint auto_increment primary key);
Query OK, 0 rows affected (0.05 sec)
-- SQL 1
mysql> insert into f1 values (127);
Query OK, 1 row affected (0.01 sec)
-- SQL 2
mysql> select * from f1;
+-----+
| c1 |
+-----+
| 127 |
+-----+
1 row in set (0.00 sec)
-- SQL 3
mysql> insert into f1 select null;
ERROR 1062 (23000): Duplicate entry '127' for key 'PRIMARY'
5. 自增列也可以显式插入有符号的值
mysql> insert into f1 values (-10),(-20),(-30);
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from f1;
+-----+
| c1 |
+-----+
| -30 |
| -20 |
| -10 |
| 127 |
+-----+
4 rows in set (0.00 sec)
如果您认为这篇文章有些帮助,还请不吝点下文章末尾的"点赞"和"在看",或者直接转发pyq,





