There are several reasons why an index doesn’t work.
1. An index column is part of a representation or function
The following SQL:
SELECT book_id FROM BOOK WHERE book_id +1 = 5;
Copy the code
Or:
SELECT book_id FROM BOOK WHERE TO_DAYS(CURRENT_DATE) - TO_DAYS(gmt_create) <= 10
Copy the code
The above two SQL columns set indexes on columns book_id and gmT_CREATE, but because they are part of expressions or functions, the indexes do not take effect, resulting in a full table scan.
2. Implicit type conversion
In both cases, we know that an index does not work, but the following implicit type conversion can cause some people to fail.
CREATE TABLE `tradelog` (
`id` int(11) NOT NULL,
`tradeid` varchar(32) DEFAULT NULL,
`operator` int(11) DEFAULT NULL,
`t_modified` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `tradeid` (`tradeid`),
KEY `t_modified` (`t_modified`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Copy the code
Execute SQL statement
SELECT * FROM tradelog WHERE tradeid=110717;
Copy the code
Tradeid = varchar(32); tradeID = varchar(32); tradeid = varchar(32); Implicitly converts a string to an integer, as follows:
mysql> SELECT * FROM tradelog WHERE CAST(tradid AS signed int) = 110717;
Copy the code
This triggers the first rule above: the index column cannot be part of a function.
3. Implicit coding transformation
This is a very subtle situation, so let’s look at this example
CREATE TABLE `trade_detail` (
`id` int(11) NOT NULL,
`tradeid` varchar(32) DEFAULT NULL,
`trade_step` int(11) DEFAULT NULL, /* Procedure */
`step_info` varchar(32) DEFAULT NULL, /* Step information */
PRIMARY KEY (`id`), KEY `tradeid` (`tradeid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Copy the code
Trade_defail is the transaction detail, tradelog is the record of the operation of the transaction detail, now to query all the operation step information of the transaction id=2, we will use the following way
SELECT d.* FROM tradelog l, trade_detail d WHERE d.tradeid=l.tradeid AND l.id=2;
Copy the code
The tradelog and trade_detail tables have different character sets, and the tradelog character set is UTF8MB4, while the trade_detail character set is UTF8, and UTF8MB4 is a superset of UTF8. So utF8 is automatically converted to UTF8MB4. That is, the above statement will be converted as follows:
SELECT d.* FROM tradelog l, trade_detail d WHERE (CONVERT(d.traideid USING utf8mb4)))=l.tradeid AND l.id=2;
Copy the code
This naturally triggers the rule that an indexed column cannot be part of a function. Alter table character set utF8MB4 to UTF8; alter table character set utF8MB4 to UTF8
mysql> SELECT d.* FROM tradelog l , trade_detail d WHERE d.tradeid=CONVERT(l.tradeid USING utf8) AND l.id=2;
Copy the code
The indexed column is now in effect.
4. Full table scan caused by order by
SELECT * FROM user ORDER BY age DESC
Copy the code
MySQL > alter table SELECT * from age; alter table SELECT * from age; alter table SELECT * from age;
SELECT age FROM user ORDER BY age DESC
Copy the code
Or add the limit condition (the data is small)
SELECT * FROM user ORDER BY age DESC limit 10
Copy the code
So we can take advantage of the index.