Inconsistency between the mysql database data type and the table field type causes the index to fail
1: Background introduction
The query speed of two tables in the mysql database is extremely slow, one table has 76015 data, and the other table has 217069 data. It is speculated that due to the inconsistency between the data type and the table field type, type conversion is required and the index invalidation leads to slow query speed.
Two: ideas & solutions
Before formulating ideas and plans, let's learn about the data types of mysql.
MySQL's data types are divided into four types : numeric type, character type date and time type binary type
numeric type can be divided into: integer type floating point number type
value type
type | illustrate | size (bytes) | memory range (unsigned) | storage range (signed) |
---|---|---|---|---|
TINYINT | very small integer | 1 | 0 〜255 | -128〜127 |
SMALLINT | small integer | 2 | 0〜65535 | -32768〜32767 |
MEDIUMINT | medium-sized integer | 3 | 0〜16777215 | -8388608〜8388607 |
INT (INTEGHR | normal sized integer | 4 | 0〜4294967295 | -2147483648〜2147483647 |
BIGINT | big integer | 8 | 0〜18446744073709551615 | -9223372036854775808〜9223372036854775807 |
FLOAT | single precision floating point | 4 | 0 and 1.175494351E-38~3.402823466E+38 | -3.402823466E+38~1.175494351E-38 |
DOUBLE | double precision floating point | 8 | 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | (-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) |
DECIMAL (M, D),DEC | Compressed "strict" fixed-point numbers | M+2 |
The storage space of DECIMAL is not fixed, but is determined by the precision value M, occupying M+2 bytes.
Note: In MySQL, fixed-point numbers are stored in the form of strings. When the accuracy requirements are relatively high (such as currency and scientific data), it is better to use the DECIMAL type. It is also easy to perform subtraction and comparison operations on the other two floating-point numbers. Something goes wrong, so you need to be careful when using floating-point numbers, and try to avoid doing floating-point comparisons.
date and time type
type | illustrate | size (bytes) |
---|---|---|
YEAR | year value | 1 |
TIME | time value or duration | 3 |
DATE | date value | 3 |
DATETIME | Mixed date and time values | 8 |
TIMESTAMP | Mixed date and time values, timestamps | 4 |
string type
type | illustrate | size (bytes) |
---|---|---|
CHAR(M) | fixed-length non-binary string | M bytes, 1<=M<=255 |
VARCHAR(M) | variable-length non-binary string | L+1 bytes, here, L<=M and 1<=M<=255 |
TINYTEXT | very small non-binary string | L+1 bytes, here, L<2^8 |
TEXT | small non-binary string | L+2 bytes, here, L<2^16 |
MEDIUMTEXT | Medium-sized non-binary string | L+3 bytes, here, L<2^24 |
LONGTEXT | large non-binary string | L+4 bytes, here, L<2^32 |
ENUM | Enumeration type, can only have one enumeration string value | 1 or 2 bytes, depending on the number of enumeration values (maximum is 65535) |
SET | A SET, String object can have zero or more SET members | 1, 2, 3, 4 or 8 bytes, depending on the number of set members (up to 64 members) |
Note: VARCHAR and TEXT types are variable-length types, and their storage requirements depend on the actual length of the column value (indicated by L in the preceding table), not on the largest possible size of the type.
例如,一个 VARCHAR(10) 列能保存一个最大长度为 10 个字符的字符串,实际的存储需要字符串的长度 L 加上一个字节以记录字符串的长度。对于字符 “abcd”,L 是 4,而存储要求 5 个字节。
二进制类型
类型 | 说明 | 大小(bytes) |
---|---|---|
BIT(M) | 位字段类型 | 大约 (M+7)/8 字节 |
BINARY(M) | 固定长度二进制字符串 | M 字节 |
VARBINARY (M) | 可变长度二进制字符串 | M+1 字节 |
TINYBLOB (M) | 非常小的BLOB | 8 |
BLOB (M) | 小 BLOB | L+2 字节,在此,L<2^16 |
MEDIUMBLOB (M) | 中等大小的BLOB | L+3 字节,在此,L<2^24 |
LONGBLOB (M) | 非常大的BLOB | L+4 字节,在此,L<2^32 |
问题复现
表索引
表字段类型
查询语句
使用数值类型进行查询
EXPLAIN
SELECT * FROM arpro_chapter_template
WHERE
is_delete =0
AND
active_id=385538879022694400
结果
索引失效
会发现type类型变成了all全表查询,索引已经失效。
使用字符串类型查询
EXPLAIN
SELECT * FROM arpro_chapter_template
WHERE
is_delete ='0'
AND
active_id=385538879022694400
结果
索引生效
结论
在进行数值类型转换时,会使我们的索引失效。补充:mysq在遇到字符串和数字比较的时候,会默认将字符串转换为数值类型进行处理,所以如果is_delete类型为数值类型,那么如果sql赋值给它的数据类型为字符串类型,那么索引是不会失效的。
我们在进行实体设计,包括给sql语句赋值的时候。最好是与数据库的数据类型保持以及,避免由于数据类型不一致的原因出现索引失效的情况。
三、扩展
总结索引失效的情况
索引列上有计算
执行sql如下:
EXPLAIN
SELECT * FROM arpro_chapter_template
WHERE
is_delete+1=1
可以看出变成了全表扫描,索引列上有计算,索引会失效。因为索引里存储的是列的原始值而不是计算后的值。
对索引使用函数
在索引列上加某个函数,sql如下:
EXPLAIN
SELECT * FROM arpro_chapter_template
WHERE
SUM(is_delete)=1
Programming full table scan, index failure. Because the original value of the column is stored in the index instead of the calculated value.
Implicit type conversions for indexes
1. If the index field is a character type, but the integer type is passed in during the conditional query, the index failure problem will occur.
2. If the index is of integer type, but the character type is passed in during the conditional query, the problem of index failure will not occur.
When mysq encounters a comparison between a string and a number, it will convert the string to a numeric type by default, so if the type of is_delete is a numeric type, then if the data type assigned to it by SQL is a string type, then the index is not will fail.
The above cases have been practiced and will not be demonstrated.
If the rest of the indexes fail, they will be supplemented later
Four: Summary
1. When dealing with databases, you need to pay special attention to whether the data types correspond, and you cannot ignore the impact of inconsistencies in data types.
2. To avoid index failure during the development process, the efficiency of not using the index and using the index is completely different.
Five: Sublimation
In the process of summarizing the blog, I defeated the irrational and strengthened a step in the rational camp.
Practice and verification have been carried out for each case.