Function Index (Generated Column) MySQL in the first and SQL optimization

Oracle MySQL is not a function of the index function of the MySQL Generated Column called "functional index" is not accurate, but can function index and achieve the same effect, it was also this feature is called "derivative column."

What is Generated Column

Generated Column value is calculated according to the expression from the definition, the following example of using official documents to be brief.

Has a length of three sides of a right triangle table storage, we all know, according to a side of the equation right triangle, the hypotenuse length can be calculated length of the two other edges, which can store only two sides in the table at right angles, The hypotenuse Generated Column by definition, create tables and insert this piece of data:

CREATE TABLE triangle (
  sidea DOUBLE,
  sideb DOUBLE,
  sidec DOUBLE AS (SQRT(sidea * sidea + sideb * sideb))
);
INSERT INTO triangle (sidea, sideb) VALUES(1,1),(3,4),(6,8);

sidea and sideb are two right-angle side, SideC is oblique, only two right-angle side when inserted insert, that is not artificially Generated Column operation (insert, update, delete), which is automatically calculated in accordance with the definition of the expression.

Query this table:

mysql> SELECT * FROM triangle;
+-------+-------+--------------------+
| sidea | sideb | sidec              |
+-------+-------+--------------------+
|     1 |     1 | 1.4142135623730951 |
|     3 |     4 |                  5 |
|     6 |     8 |                 10 |
+-------+-------+--------------------+

Generated Column definition syntax

Generated Column definition syntax is as follows:

col_name data_type [GENERATED ALWAYS] AS (expr)
  [VIRTUAL | STORED] [NOT NULL | NULL]
  [UNIQUE [KEY]] [[PRIMARY] KEY]
  [COMMENT 'string']

Keyword "AS" indicates the field is derived, is Generated Column, behind AS is calculated for expression. GENERATED ALWAYS make better defined, it can be omitted.

VIRTUAL STORED and two types of Generated Column, indicate how the field values ​​are stored:

  • VIRTUAL: Virtual Generated Column value will not be persisted to disk, save only in the data dictionary (metadata tables), will be calculated BEFORE trigger immediately after each read.
  • STORED: Stored Generated Column values ​​will be persisted to disk, rather than calculated each time when reading.

If not specified, then, MySQL will default VIRTUAL realized in the form of, STORED need more disk space, there is no obvious performance advantage, so the general use VIRTUAL.

Generated Column defined points

  • In general, Generated Column can use built-in functions and operators defined. If given the same data, multiple calls to produce the same result, such a definition is explicitly permitted. Otherwise, the definition will fail, for example NOW(), CURRENT_USER(), CONNECTION_ID()the definition will fail.
  • Custom functions and stored procedures, are not allowed.
  • Variables, such as the system variables, does not allow the use of other custom variable.
  • Subqueries are not allowed.
  • Generated Column may be defined in other dependent Generated Column fields, but depends derived fields you must be defined in front of it. If only non-dependent field is derived, the order is not defined.
  • Since growth AUTO_INCREMENTis not allowed.
  • Since the growth column is not used in the definition of Generated Column.
  • As of MySQL 5.7.10, if the expression evaluates to a function result in truncated or provide incorrect input, the create table statement will terminate and return DDL operations.

A SQL optimization

By slow query log to find a slow SQL, the implementation plan is as follows:

mysql> EXPLAIN
SELECT
    c.id,
    b.customer_status
FROM
    t_core_customer c
    INNER JOIN t_core_customer_bizinfo b ON c.id = b.customer_id AND b.biz_id = 'maintain' 
WHERE
    REPLACE ( REPLACE ( c.customer_name, '(', '(' ), ')', ')' ) = '天津买斯扣科技有限公司';
+----+-------------+-------+------------+--------+----------------------------------+---------+---------+--------------------------------+---------+----------+-------------+
| id | select_type | table | partitions | type   | possible_keys                    | key     | key_len | ref                            | rows    | filtered | Extra       |
+----+-------------+-------+------------+--------+----------------------------------+---------+---------+--------------------------------+---------+----------+-------------+
|  1 | SIMPLE      | b     | NULL       | ALL    | idx_core_customer_bizinfo_cidbid | NULL    | NULL    | NULL                           | 1263918 |    10.00 | Using where |
|  1 | SIMPLE      | c     | NULL       | eq_ref | PRIMARY                          | PRIMARY | 110     | b.customer_id                  |       1 |   100.00 | Using where |
+----+-------------+-------+------------+--------+----------------------------------+---------+---------+--------------------------------+---------+----------+-------------+
2 rows in set (0.05 sec)

Customer table has 1.17 million rows of data, this SQL execution took more than four seconds, you can see through the implementation of programs, the customer table does not take the index and full table scan, index customer_name field due to replace function is not use to.

Increase Generated Column:

ALTER TABLE `t_core_customer` 
ADD COLUMN `customer_name_replaced` varchar(200)  AS (REPLACE(REPLACE(customer_name, '(', '(' ), ')', ')' )); 

Create an index:

ALTER TABLE `t_core_customer` 
ADD INDEX `customer_name_replaced`(`customer_name_replaced`) USING BTREE;

Then look to optimize execution plan:

mysql> EXPLAIN
SELECT
    c.id,
    b.customer_status
FROM
    t_core_customer c
    INNER JOIN t_core_customer_bizinfo b ON c.id = b.customer_id AND b.biz_id = 'maintain' 
WHERE
    REPLACE ( REPLACE ( c.customer_name, '(', '(' ), ')', ')' ) = '天津买斯扣科技有限公司';
+----+-------------+-------+------------+------+----------------------------------+----------------------------------+---------+-----------------------------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys                    | key                              | key_len | ref                         | rows | filtered | Extra |
+----+-------------+-------+------------+------+----------------------------------+----------------------------------+---------+-----------------------------+------+----------+-------+
|  1 | SIMPLE      | c     | NULL       | ref  | PRIMARY,customer_name_replaced   | customer_name_replaced           | 603     | const                       |    1 |   100.00 | NULL  |
|  1 | SIMPLE      | b     | NULL       | ref  | idx_core_customer_bizinfo_cidbid | idx_core_customer_bizinfo_cidbid | 222     | c.id,const                  |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+------+----------------------------------+----------------------------------+---------+-----------------------------+------+----------+-------+
2 rows in set (0.40 sec)

Implementation plan properly, use the index, SQL time-consuming to less than 10 milliseconds.

Guess you like

Origin www.cnblogs.com/cellei/p/12443294.html