我有一个MySQL 8 InnoDB压缩表,带有索引:
set global innodb_file_per_table=1;
create table t (id int primary key auto_increment,
key varchar(200), value varchar(200))
row_format=compressed engine=innoDB;
create index key_index on t(key) using BTREE;
create index value_index on t(value) using BTREE;
对于2000万个项目,一个(前缀)搜索就像
select * from t where email like "hello%"
需要几毫秒(感谢索引!)...但是像这样的 (中缀) 搜索
select * from t where email like "%hello%"
需要40秒
**如何加快查询速度?**我读过https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html,但我不想使用太复杂的工具:什么是最轻的解决方案,能够进行搜索,如:
******abc***************************
| | |
| an exact sequence |
| |
0, 1 or many characters 0, 1 or many characters
注意:我使用mysql-8.0.33-winx64
和Python(import mysql.connector
)。
1条答案
按热度按时间mwkjh3gx1#
如果全文索引对于您的口味来说太复杂,那么只有其他方法可以加快查询速度:
在模式的开始处使用通配符显示的查询必然要进行表扫描,即使您有一个b树索引。这种模式匹配不能使用b树索引。
想想电话簿的类比。这本书是按姓和名排序的。如果你按某人的姓查找,你可以快速搜索,因为它是排序的。但是如果你搜索的人的姓氏有一些字符模式 * 在中间 *,事实上,这本书是按姓氏排序没有帮助。你仍然需要查看每一页上的每一个条目。这就像数据库中的表扫描。
MySQL中的FULLTEXT索引可能也没有帮助。如果您搜索的是整个单词,而不是任意的模式或子字符串,它会很有帮助,因为它不支持前导通配符搜索。
https://dev.mysql.com/doc/refman/8.0/en/fulltext-boolean.html说:
*
星号用作截断(或通配符)运算符。与其他运算符不同,它被附加到要受影响的单词后面。如果单词以
*
运算符之前的单词开始,则单词匹配。你不能在单词前使用这个通配符,只能在单词前缀后使用。这正是MySQL当前版本中实现此功能的方式。
MySQL支持生成的列和这些列的索引,所以你可以在
LIKE
表达式上创建一个索引:然后在该列中搜索为真的行:
这将使用索引,但仅用于在生成的列的定义中固定的模式
'%hello%'
。不能生成为任何参数都带参数的生成列。基本上,没有好的选择。为任何新模式创建索引的代价至少与执行表扫描一样高(实际上更高)。