mysql57函数索引

在之前的版本中mysql中是没有函数索引的,所以对于在列上添加函数运算的查询只能走全表扫,在57中虽然没有明确的函数索引创建方式,但是可以通过虚拟列的方式变相实现。下面的例子是在oow大会中学习到的。

mysql> show create table employees;
+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table     | Create Table                                                                                                                                                                                                                                                                                 |
+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| employees | CREATE TABLE `employees` (
  `emp_no` int(11) NOT NULL,
  `birth_date` date NOT NULL,
  `first_name` varchar(14) NOT NULL,
  `last_name` varchar(16) NOT NULL,
  `gender` enum('M','F') NOT NULL,
  `hire_date` date NOT NULL,
  PRIMARY KEY (`emp_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> desc employees;
+------------+---------------+------+-----+---------+-------+
| Field      | Type          | Null | Key | Default | Extra |
+------------+---------------+------+-----+---------+-------+
| emp_no     | int(11)       | NO   | PRI | NULL    |       |
| birth_date | date          | NO   |     | NULL    |       |
| first_name | varchar(14)   | NO   |     | NULL    |       |
| last_name  | varchar(16)   | NO   |     | NULL    |       |
| gender     | enum('M','F') | NO   |     | NULL    |       |
| hire_date  | date          | NO   |     | NULL    |       |
+------------+---------------+------+-----+---------+-------+
6 rows in set (0.00 sec)

mysql> select count(*) from employees;
+----------+
| count(*) |
+----------+
|   300024 |
+----------+
1 row in set (0.18 sec)

mysql> select * from employees limit 1\G
*************************** 1. row ***************************
    emp_no: 10001
birth_date: 1953-09-02
first_name: Georgi
 last_name: Facello
    gender: M
 hire_date: 1986-06-26
1 row in set (0.00 sec)

mysql> ALTER TABLE employees ADD COLUMN past_date
    -> date GENERATED ALWAYS AS
    -> (adddate(hire_date,INTERVAL 18 YEAR)) VIRTUAL;
Query OK, 0 rows affected (0.19 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc employees;
+------------+---------------+------+-----+---------+-------------------+
| Field      | Type          | Null | Key | Default | Extra             |
+------------+---------------+------+-----+---------+-------------------+
| emp_no     | int(11)       | NO   | PRI | NULL    |                   |
| birth_date | date          | NO   |     | NULL    |                   |
| first_name | varchar(14)   | NO   |     | NULL    |                   |
| last_name  | varchar(16)   | NO   |     | NULL    |                   |
| gender     | enum('M','F') | NO   |     | NULL    |                   |
| hire_date  | date          | NO   |     | NULL    |                   |
| past_date  | date          | YES  |     | NULL    | VIRTUAL GENERATED |
+------------+---------------+------+-----+---------+-------------------+
7 rows in set (0.01 sec)

mysql> select * from employees limit 1\G
*************************** 1. row ***************************
    emp_no: 10001
birth_date: 1953-09-02
first_name: Georgi
 last_name: Facello
    gender: M
 hire_date: 1986-06-26
 past_date: 2004-06-26
1 row in set (0.00 sec)

mysql> select * from employees limit 2\G
*************************** 1. row ***************************
    emp_no: 10001
birth_date: 1953-09-02
first_name: Georgi
 last_name: Facello
    gender: M
 hire_date: 1986-06-26
 past_date: 2004-06-26
*************************** 2. row ***************************
    emp_no: 10002
birth_date: 1964-06-02
first_name: Bezalel
 last_name: Simmel
    gender: F
 hire_date: 1985-11-21
 past_date: 2003-11-21
2 rows in set (0.00 sec)

mysql> CREATE INDEX past_date_idx on
    -> employees(past_date);
Query OK, 0 rows affected (4.48 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show create table employees;
+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table     | Create Table                                                                                                                                                                                                                                                                                                                                                                                                         |
+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| employees | CREATE TABLE `employees` (
  `emp_no` int(11) NOT NULL,
  `birth_date` date NOT NULL,
  `first_name` varchar(14) NOT NULL,
  `last_name` varchar(16) NOT NULL,
  `gender` enum('M','F') NOT NULL,
  `hire_date` date NOT NULL,
  `past_date` date GENERATED ALWAYS AS ((`hire_date` + interval 18 year)) VIRTUAL,
  PRIMARY KEY (`emp_no`),
  KEY `past_date_idx` (`past_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> explain select * from employees where
    -> adddate(hire_date,INTERVAL 18 YEAR)>=NOW();
+----+-------------+-----------+------------+-------+---------------+---------------+---------+------+------+----------+-------------+
| id | select_type | table     | partitions | type  | possible_keys | key           | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-----------+------------+-------+---------------+---------------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | employees | NULL       | range | past_date_idx | past_date_idx | 4       | NULL |    1 |   100.00 | Using where |
+----+-------------+-----------+------------+-------+---------------+---------------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

看到通过这种方式,对于现有的代码可以不用修改就可以使用上索引。

你可能感兴趣的:(MYSQL)