Ali: The condition field is indexed, why is the query so slow?

Preface

Recently, the company had a different view on the issue of using the DATE_FORMAT function during code review. Will the specific DATE_FORMAT affect the index? Under what circumstances will it have an impact? Nothing happened on the weekend, a wave of tests through the mysql execution plan.

Use explain analysis

The execution plan is to show how Mysql executes a Sql statement, using EXPLAIN. The output includes the order of Sql query, whether to use the index, and the index information used, as shown in the figure

Ali: The condition field is indexed, why is the query so slow?

id: Indicates the order of the select operation table in the query, executed in order from largest to sequential

select_type : This represents the type of selection, optional values ​​are: SIMPLE (simple)

Ali: The condition field is indexed, why is the query so slow?

type : This attribute represents the type of access, and there are many types of access. The most common ones include the following: ALL (full table scan), index (index scan), range (range scan), ref (non-unique index scan), eq_ref (unique index scan), (const) constant reference, The access speed is from slow to fast. Among them: range (range) is common with between and …, greater than and less than this case. Tip: You can check whether slow SQL is indexed or not, and what index is gone, can be checked through this property.

Ali: The condition field is indexed, why is the query so slow?

table: represents the table queried by the statement

possible_keys: As the name suggests, this attribute gives the query statement, the index that may be taken, (such as the name of the index on some fields). The provided here is only a reference, not the actual index, which will result in possible_Keys not being Null, the key is empty phenomenon.

key : Displays the indexes actually used by MySQL, including the primary key index (PRIMARY), or the name of the self-built index.

key_len: Indicates the number of bytes used by the index,

ref: connection matching condition, if the primary key index is taken, the value is: const, for full table scan, it is a null value

rows: The number of rows to be scanned, that is, how many rows need to be scanned to get the target number of rows, which is generally greater than the number of returned rows. Under normal circumstances, the smaller the rows, the higher the efficiency, and most of the SQL optimizations are reducing the size of this value. (Note: Ideally, the number of scanned rows is theoretically the same as the actual number of returned rows, but this situation is extremely small, such as related queries, the number of scanned rows will be greatly increased than the number of returned rows)

Extra : This attribute is very important. The attribute includes the real situation information when executing SQL. As above, the "using where" is used, which means the value obtained by using where filter. Commonly used are: "Using temporary": Use Temporary table "using filesort": use file sort

Table statement and data insertion sql as shown:

Ali: The condition field is indexed, why is the query so slow?

If there is a partner who needs verification, also attach SQL, which is consistent with the above picture:

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `age` int(11) NULL DEFAULT NULL,
  `birth_date` date NULL DEFAULT NULL,
  `is_delete` tinyint(1) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `name`(`name`) USING BTREE,
  INDEX `age`(`age`) USING BTREE,
  INDEX `birth_date`(`birth_date`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 22 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, '小明1', 1, '2000-01-01', 0);
INSERT INTO `user` VALUES (2, '小明2', 2, '2001-01-02', 0);
INSERT INTO `user` VALUES (3, '小明3', 3, '2002-01-03', 0);
INSERT INTO `user` VALUES (4, '小明4', 4, '2003-01-04', 0);
INSERT INTO `user` VALUES (5, '小明5', 5, '2004-01-05', 0);
INSERT INTO `user` VALUES (6, '小明6', 6, '2005-01-06', 0);
INSERT INTO `user` VALUES (7, '小明7', 7, '2006-01-07', 0);
INSERT INTO `user` VALUES (8, '小明8', 8, '2007-01-08', 0);
INSERT INTO `user` VALUES (9, '小明9', 9, '2008-01-09', 0);
INSERT INTO `user` VALUES (10, '小明1', 10, '2009-01-10', 0);
INSERT INTO `user` VALUES (11, '小明11', 11, '2010-01-11', 0);
INSERT INTO `user` VALUES (12, '小明12', 12, '2011-01-12', 0);
INSERT INTO `user` VALUES (13, '小明13', 13, '2012-01-13', 0);
INSERT INTO `user` VALUES (14, '小明14', 14, '2013-01-14', 0);
INSERT INTO `user` VALUES (15, '小明15', 15, '2014-01-15', 0);
INSERT INTO `user` VALUES (16, '小明16', 16, '2015-01-16', 0);
INSERT INTO `user` VALUES (17, '小明17', 17, '2016-01-17', 0);
INSERT INTO `user` VALUES (18, '小明18', 18, '2017-01-18', 0);
INSERT INTO `user` VALUES (19, '小明19', 19, '2018-01-19', 0);
INSERT INTO `user` VALUES (20, '小明20', 20, '2019-01-20', 0);
INSERT INTO `user` VALUES (21, '小明21', 21, '2020-01-21', 0);

Verification process

Note: The database used in this article is mysql: 5.7.24.

1. No DATE_FORMAT function

The first way:

explain select * from user where birth_date <= '2009-10-10';

Ali: The condition field is indexed, why is the query so slow?

The key may be used as shown in the figure above: birth_date.

The second way:

EXPLAIN SELECT * FROM USER WHERE birth_date <= '2009-10-10' and birth_date >= '2009-10-10';

Ali: The condition field is indexed, why is the query so slow?

The key is used as shown in the figure above: birth_date.

2. Use the DATE_FORMAT function

The first way:

EXPLAIN
SELECT
 *
FROM
 USER
WHERE
 birth_date >= DATE_FORMAT('2019-10-10', '%Y-%m-%d');

EXPLAIN
SELECT
 *
FROM
 USER
WHERE
 birth_date >= DATE_FORMAT('2019-10-10', '%Y-%m-%d')
AND birth_date <= DATE_FORMAT('2020-12-10', '%Y-%m-%d');

Ali: The condition field is indexed, why is the query so slow?

The second way:

EXPLAIN
SELECT
 *
FROM
 USER
WHERE
 DATE_FORMAT(birth_date, '%Y-%m-%d') >= '2019-10-10';

EXPLAIN
SELECT
 *
FROM
 USER
WHERE
 DATE_FORMAT(birth_date, '%Y-%m-%d') >= '2019-10-10'
AND DATE_FORMAT(birth_date, '%Y-%m-%d') <= '2020-12-10';

Ali: The condition field is indexed, why is the query so slow?

The above two sets of SQL were tested by adding DATE_FORMAT to the fields and parameters. The results are shown in the figure. The birth_date index is not effective,  mainly depending on the field key .

Therefore, in the development process, you should avoid using this type of function, otherwise it may cause index failure and full table scan.

to sum up

Choose according to the actual situation :

①Use the first method in DATE_FORMAT, use DATE_FORMAT in the query parameter instead of the query field .

EXPLAIN
SELECT
 *
FROM
 USER
WHERE
 birth_date >= DATE_FORMAT('2019-10-10', '%Y-%m-%d')
AND birth_date <= DATE_FORMAT('2020-12-10', '%Y-%m-%d');

②Do not use the second method in DATE_FORMAT, query according to the range, such as query one

-- 举例:
EXPLAIN SELECT
 *
FROM
 USER
WHERE
 create_time >= '2026-10-24 00:00:00'
AND create_time <= '2026-10-24 23:59:59';

Write at the end

Welcome everyone to pay attention to my public account [The wind and waves are as quiet as the code ], a large number of Java-related articles, learning materials will be updated in it, and the compiled materials will also be placed in it.

If you think the writing is good, just like it and add a follower! Pay attention, don’t get lost, keep updating! ! !

Guess you like

Origin blog.51cto.com/14957073/2562904