用于计数和显示(列中的不同值)的 Sql 查询优化,按其他两列分组
Posted
技术标签:
【中文标题】用于计数和显示(列中的不同值)的 Sql 查询优化,按其他两列分组【英文标题】:Sql Query Optimization for counting and displaying (distinct value in column), grouped by other two columns 【发布时间】:2018-11-26 04:11:57 【问题描述】:从 A、B 和 C 列中,我计算表按 A、B 分组的不同 C。 下面是示例表:
输出应该类似于:
我正在使用 wamp 服务器在本地计算机上运行 phpMyAdmin 进行测试。我的数据库有 500000 行。我使用了以下查询,运行查询花费了 180 多秒。
select A, B, count(distinct C)
from table
group by A, B
order by count(DISTINCT C) desc
是否有任何最佳查询可以用于相同的结果,从而减少运行时间?或者,是因为我的表中有大量数据吗?
【问题讨论】:
您只需要索引您的列,它们用于加快查询速度,并且数据库搜索引擎将使用它们来非常快速地定位记录。看到这个:dev.mysql.com/doc/refman/5.5/en/column-indexes.html 由于您是新手,请勿在此处放置屏幕截图,请将逗号或管道分隔值放在表格中。请参阅 sqlfiddle.com 查询是直截了当的。不要试图改变它。为了计数,必须读取整个表并对其进行排序。覆盖索引 (create index idx on table(a,b,c)
) 可能会有所帮助。然后 DBMS 可能会读取整个索引而不是整个表,并找到数据 prêt-à-porter。但是,我不知道遍历这样一个索引的所有分支需要做多少工作。也许它更快,也许不是。
毕竟,排序应该是几秒钟的事情(你可以在你的电脑上用 Excel 试试这个),那么你的电脑真的从磁盘读取记录需要这么长时间吗?然后,您可能想要对您的表 (dev.mysql.com/doc/refman/8.0/en/innodb-file-defragmenting.html) 或整个硬盘进行碎片整理。 (但好吧,可能 MySQL 在此类操作上仍然很慢,我们对此无能为力。)
【参考方案1】:
为了提高性能,您需要在表上添加 Composite Index 或 (A, B, C)
。
ALTER TABLE your_table_name
ADD INDEX(A,B,C);
【讨论】:
MySQL 是否真的将这个索引用于他的查询? @GordonLinoff - 我希望它有两个原因:1. 它是GROUP BY
的最佳选择,2. 它是“覆盖”。尽管如此,500K 行的索引扫描可能不会比相同行数的表扫描快很多。
@RickJames。 . .我没有很好地表达我的问题。这会消除GROUP BY
通常进行的排序吗?我的猜测是COUNT(DISTINCT)
会混淆优化器。
@GordonLinoff - 如果它可以按GROUP BY
顺序遍历表(或索引),则不需要排序。 COUNT(DISTINCT ..)
可能会通过一些内存技术来尝试。运行EXPLAIN FORMAT=JSON SELECT ...
——那里可能有一些证据。以上是关于用于计数和显示(列中的不同值)的 Sql 查询优化,按其他两列分组的主要内容,如果未能解决你的问题,请参考以下文章
SQL:根据 B 列中的布尔值更改 SELECT 查询以在 A 列上显示不同的值