CREATE TABLE t1 (id INT PRIMARY KEY, c INT) ENGINE=Memory;
CREATE TABLE t2 (id INT PRIMARY KEY, c INT) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9),(0,0);
INSERT INTO t2 VALUES (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9),(0,0);
-- 0在最后
mysql> SELECT * FROM t1;
+----+------+
| id | c |
+----+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 7 |
| 8 | 8 |
| 9 | 9 |
| 0 | 0 |
+----+------+
-- 0在最前
mysql> SELECT * FROM t2;
+----+------+
| id | c |
+----+------+
| 0 | 0 |
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 7 |
| 8 | 8 |
| 9 | 9 |
+----+------+
t2的数据组织方式,主键索引上的值是有序存储的,执行SELECT *时,按叶子节点从左到右扫描
ALTER TABLE t1 ADD INDEX a_btree_index USING BTREE (id);
-- 优化器选择了a_btree_index索引
mysql> EXPLAIN SELECT * FROM t1 WHERE id<5;
+----+-------------+-------+------------+-------+-----------------------+---------------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+-----------------------+---------------+---------+------+------+----------+-------------+
| 1 | SIMPLE | t1 | NULL | range | PRIMARY,a_btree_index | a_btree_index | 4 | NULL | 6 | 100.00 | Using where |
+----+-------------+-------+------------+-------+-----------------------+---------------+---------+------+------+----------+-------------+
-- 0在最前面
mysql> SELECT * FROM t1 WHERE id<5;
+----+------+
| id | c |
+----+------+
| 0 | 0 |
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
+----+------+
-- 强制走主键索引,为哈希索引,走全表扫描
mysql> SELECT * FROM t1 FORCE INDEX(PRIMARY) WHERE id<5;
+----+------+
| id | c |
+----+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 0 | 0 |
+----+------+
DELETE FROM t1 WHERE id=5;
INSERT INTO t1 VALUES (10,10);
mysql> SELECT * FROM t1;
+----+------+
| id | c |
+----+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 10 | 10 |
| 6 | 6 |
| 7 | 7 |
| 8 | 8 |
| 9 | 9 |
| 0 | 0 |
+----+------+
不推荐在生产环境使用Memory表
Memory表不支持行锁,只支持表锁(并不是MDL锁),对并发访问的支持不够好。
SessionA | SessionB | SessionC |
---|---|---|
UPDATE t1 SET id=SLEEP(50) WHERE id=1; |
||
SELECT * FROM t1 WHERE id=2;(Wait 50s) |
||
SHOW PROCESSLIST; |
mysql> SHOW PROCESSLIST;
+----+-----------------+-----------+------+---------+--------+------------------------------+---------------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-----------------+-----------+------+---------+--------+------------------------------+---------------------------------------+
| 4 | event_scheduler | localhost | NULL | Daemon | 206928 | Waiting on empty queue | NULL |
| 21 | root | localhost | test | Query | 27 | User sleep | UPDATE t1 SET id=SLEEP(50) WHERE id=1 |
| 22 | root | localhost | test | Query | 16 | Waiting for table level lock | SELECT * FROM t1 WHERE id=2 |
| 23 | root | localhost | test | Query | 0 | starting | SHOW PROCESSLIST |
+----+-----------------+-----------+------+---------+--------+------------------------------+---------------------------------------+
数据库重启后,所有的Memory表都会被清空
PS: 参考资料 《MySQL实战45讲》