如何加速选择比如mysql中的多列查询?

tyu7yeag  于 2021-06-20  发布在  Mysql
关注(0)|答案(8)|浏览(437)

我有一个mysql表,我经常使用它 SELECT x, y, z FROM table WHERE x LIKE '%text%' OR y LIKE '%text%' OR z LIKE '%text%' 查询。任何一种索引都有助于加快速度吗?
表中有几百万条记录。如果有什么东西会加速搜索,会不会严重影响数据库文件的磁盘使用率和搜索速度 INSERT 以及 DELETE 陈述(不 UPDATE 曾经表演过)

更新:发帖后很快,我看到了很多关于这个方式的信息和讨论 LIKE 在查询中使用;我想指出必须使用的解决方案 LIKE '%text%' (也就是说,我要查找的文本在前面加了一个%通配符)。数据库也必须是本地的,原因很多,包括安全性。

q3qa4bjr

q3qa4bjr1#

如果搜索条件以通配符开头,则索引不能用于加快查询速度: LIKE '%text%' 索引可以(也可以根据选择性)用于以下形式的搜索项: LIKE 'text%'

bqjvbblv

bqjvbblv2#

索引无助于文本与前导通配符匹配,索引可用于:

LIKE 'text%'

但我猜这不会解决问题。对于这种类型的查询,如果您想缩放可以搜索的记录数量,那么您确实应该查看全文搜索提供程序。我的首选提供商是斯芬克斯,功能齐全/快速等。lucene也值得一看。myisam表上的全文索引也会起作用,但最终对任何有大量写操作的数据库使用myisam并不是一个好主意。

svmlkihl

svmlkihl3#

我要补充的是,在某些情况下,如果所查看的字段经常为空或包含常量,则可以使用索引和like/rlike来加快查询速度。
在这种情况下,似乎可以通过添加带有固定值的“and”子句来限制使用索引访问的行。
我尝试在一个通常不包含很多标签的大表中搜索“标签”。 SELECT * FROM objects WHERE tags RLIKE("((^|,)tag(,|$))" AND tags!='' 如果您在标记上有一个索引,您将看到它用于限制正在搜索的行。

tez616oj

tez616oj4#

也许你可以尝试升级mysql5.1到mysql5.7。
我有七万张唱片。并运行以下sql:

select * from comics where name like '%test%';

在mysql5.1中需要2000ms。在mysql5.7或mysql5.6中需要200毫秒。

vngu2lb8

vngu2lb85#

索引不会加快查询速度,因为对于文本列,索引是从左开始索引n个字符的。当您喜欢“%text%”时,它不能使用索引,因为在文本之前可以有可变数量的字符。
您应该做的是根本不使用这样的查询。相反,您应该使用类似fts(全文搜索)的东西,mysql支持myisam表。为非myisam表自己创建这样的索引系统也很容易,您只需要一个单独的索引表,将单词及其相关id存储在实际的表中。
更新
MySQL5.6+支持innodb表的全文搜索。

mwngjboj

mwngjboj6#

另一种避免全表扫描的方法是选择子字符串并在having语句中检查它们:

SELECT 
    al3.article_number,
    SUBSTR(al3.article_number, 2, 3) AS art_nr_substr,
    SUBSTR(al3.article_number, 1, 3) AS art_nr_substr2,
    al1.*
FROM
    t1 al1 
    INNER JOIN t2 al2 ON al2.t1_id = al1.id
    INNER JOIN t3 al3 ON al3.id = al2.t3_id
WHERE
    al1.created_at > '2018-05-29'
HAVING 
    (art_nr_substr = "FLA" OR art_nr_substr = 'VKV' OR art_nr_subst2 = 'PBR');
piok6c0g

piok6c0g7#

添加全文索引并对()使用match()。

普通索引不会帮助您 like 查询,尤其是那些在搜索词的两边都使用通配符的查询。
您可以在感兴趣的列上添加全文索引,然后使用 MATCH() AGAINST() 查询以搜索那些全文索引。
在需要的列上添加全文索引:

ALTER TABLE table ADD FULLTEXT INDEX index_table_on_x_y_z (x, y, z);

然后查询这些列:

SELECT * FROM table WHERE MATCH(x,y,z) AGAINST("text")

从我们的试验中,我们发现在一个有100多万条记录的表中,这些查询大约需要1毫秒。不错,尤其是和等价的通配符相比 LIKE %text% 需要16400ms的查询。

基准 MATCH(x,y,z) AGAINST("text") 需要1毫秒 LIKE %text% 需要16400毫秒

快16400倍!

iklwldmw

iklwldmw8#

另一种方式:
您可以将这些字符串反转并使用

SELECT x, y, z FROM table WHERE x LIKE 'text%' OR y LIKE 'text%' OR z LIKE 'text%' OR xRev LIKE 'txet%' OR yRev LIKE 'txet%' OR zRev LIKE 'txet%'

如何添加存储的持久化列的示例

ALTER TABLE table ADD COLUMN xRev VARCHAR(N) GENERATED ALWAYS AS REVERSE(x) stored;

然后在上创建索引 xRev , yRev 等。

相关问题