# Covering index
mysql> ALTER TABLE t2 ADD v_lang varchar(16) AS (CONCAT('OK-', lang)), ADD KEY(v_lang);
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> EXPLAIN SELECT v_lang, COUNT(*) FROM t2 GROUP BY v_lang;
+----+-------------+-------+------------+-------+---------------+--------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+--------+---------+------+------+----------+-------------+
| 1 | SIMPLE | t2 | NULL | index | v_lang | v_lang | 19 | NULL | 10 | 100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+--------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.01 sec)
# 범위 검색으로 ORDER BY 까지 KEY가 사용되지 않을 때, 활용법
mysql> SHOW INDEX FROM t2;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| t2 | 0 | PRIMARY | 1 | id | A | 17 | NULL | NULL | | BTREE | | |
| t2 | 1 | age | 1 | age | A | 8 | NULL | NULL | YES | BTREE | | |
| t2 | 1 | age | 2 | created_at | A | 17 | NULL | NULL | YES | BTREE | | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
3 rows in set (0.00 sec)
mysql> EXPLAIN SELECT * FROM t2 WHERE age < 20 ORDER BY created_at;
+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+---------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+---------------------------------------+
| 1 | SIMPLE | t2 | NULL | range | age | age | 2 | NULL | 2 | 100.00 | Using index condition; Using filesort |
+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+---------------------------------------+
1 row in set, 1 warning (0.00 sec)
mysql> ALTER TABLE t2 ADD is_adult tinyint AS (IF(age < 20, 1, 0)), ADD KEY (is_adult, created_at);
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> EXPLAIN SELECT * FROM t2 WHERE is_adult = 1 ORDER BY created_at DESC;
+----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------------+
| 1 | SIMPLE | t2 | NULL | ref | is_adult | is_adult | 2 | const | 2 | 100.00 | Using where |
+----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.01 sec)
# CHECK 제약으로 응용
mysql> ALTER TABLE t2 ADD age_check tinyint AS (IF(age > 100 , null, 1)) NOT NULL;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> INSERT INTO t2 (lang, age) VALUES ('test', 101);
ERROR 1048 (23000): Column 'age_check' cannot be null