用于计数和显示(列中的不同值)的 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 列上显示不同的值

SQL Server:选择一列的计数,同时检查另一列中的不同值

计数值出现在 MySQL 中特定列中的次数

SQL Count 不计算列中的“NULL”

SQL如何查询出某一列中不同值出现的次数?

关于我的这个 SQL Server 查询的问题