当结果很少时 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 查询很慢的主要内容,如果未能解决你的问题,请参考以下文章

使用 NOT IN ( SELECT ... ) 时查询执行速度很慢

mongodb页面展示列表时遇到展示慢的问题

SQL---分页查询

大结果在任何地方都很慢,但在本地

数据量很大,分页查询很慢,优化方案

打开多个查询时访问 SQL-Server 很慢