当结果很少时 MySQL-select 查询很慢
Posted
技术标签:
【中文标题】当结果很少时 MySQL-select 查询很慢【英文标题】:MySQL-select query is very slow when there are a few results 【发布时间】:2021-01-20 18:40:43 【问题描述】:我的数据库中有table1
1M 行。
columns: id, name, timestamp, tag, r, g, b
indexes: primary: id, index: timestamp, index: (tag,r,g,b)
每一行都有一个标签(它是一个整数)和一个颜色,它由它的组件 (r,g,b) 保存在单独的列中。我的查询应该是这样的:
SELECT * from table1 WHERE tag=... AND (r>... AND r<... AND g>... AND g<... AND b>... AND b<...) ORDER BY timestamp DESC LIMIT 24;
问题是当数据库中只有很少的记录用于选定的过滤器(标签和颜色)时,查询非常慢(15 秒)。还值得注意的是,当我从查询中删除 ORDER BY timestamp DESC
时,它运行得非常快,即使有一些结果。如何解决问题,让查询快速?
【问题讨论】:
表格有多少行? 【参考方案1】:我不确定您所说的“很少”是什么意思,但 15 秒似乎很长。
您希望在 (tag, r, g, b)
上为此查询创建索引。
也就是说,这不是一个最佳索引;或者更准确地说,它与您在 mysql 中获得的一样最佳。您想要的真正索引类型是 RD-Tree,它针对不同维度上的范围进行了优化。主要用例是 GIS(地理信息系统)。
但是,我不认为 MySQL 支持 RD-Trees 作为通用索引类型。希望tag
具有高度选择性,并且上述索引能够正常工作。
【讨论】:
正如我在问题中提到的,我目前正在使用(tag, r, g, b)
上的索引,但是例如,当结果少于 1000 个时,它需要很长时间。
我无法理解Hopefully, tag is highly selective and the above index will work well.
的意思,您能解释一下吗?
@Soheil 。 . .单个标签匹配表中的少数记录。【参考方案2】:
INDEX(tag, timestamp)
可能会有所帮助。
一般的问题是优化器看到两个半有用的索引,但没有足够的线索来选择哪一个。然后它会选择不太有利的那个。
当您对 g 或 b 的选择相对狭窄时,添加这些可能会有所帮助:
INDEX(tag, g)
INDEX(tag, b)
不幸的是,WHERE
子句中有 4 个“范围”(时间戳、r、g、b),优化器只能使用一个。我将tag
放在每个前面(包括你现存的(tag, r, g, b)
,不会超出r
)。
=
测试应该先行;索引可以以一个范围结束;任何后续范围测试(在您的情况下为 g,b)都将在索引中被忽略。
【讨论】:
非常感谢您的解释。我尝试了(标签,时间戳)索引,但没有明显帮助。最后,我确信我必须重新定义一些搜索逻辑并将范围查询替换为=
查询。以上是关于当结果很少时 MySQL-select 查询很慢的主要内容,如果未能解决你的问题,请参考以下文章