计数查询耗时太长 - 超过24小时已过

use*_*185 2 mysql sql database

好的,我可能做错了什么,但是按照用户的建议,我运行这个查询:

SELECT id, item, 
   (SELECT COUNT(item) FROM Table1 WHERE id=a.id AND item=a.item) cnt
FROM (SELECT DISTINCT a.id,b.item FROM Table1 a, Table1 b) a
ORDER BY id, item;
Run Code Online (Sandbox Code Playgroud)

在这张桌子上:

ID         ITEM
-----------------
0001        345
0001        345
0001        120
0002        567
0002        034
0002        567
0003        567
0004        533
0004        008
...
Run Code Online (Sandbox Code Playgroud)

为了得到这个结果:

ID  ITEM    CNT
1   8       0
1   34      0
1   120     1
1   345     2
1   533     0
1   567     0
2   8       0
2   34      1
...
Run Code Online (Sandbox Code Playgroud)

但它花了太长时间,一天后查询仍在运行......有没有办法提高性能?我有大约400万行

谢谢

Gor*_*off 6

您的查询非常复杂.我觉得你只是想计算的组合iditem.如果是这样,这是一个简单的聚合:

select id, item, count(*)
from Table1 a
group by id, item;
Run Code Online (Sandbox Code Playgroud)

如果要显示所有ID和项目,请使用驱动程序表:

select driver.id, driver.item, coalesce(count(t1.id), 0)
from (select id.id, item.item
      from (select distinct id from Table1) id cross join
           (select distinct item from Table1) item
     ) driver left outer join
     Table1 t1
     on driver.id = t1.id and driver.item = t1.item
group by driver.id, driver.item;
Run Code Online (Sandbox Code Playgroud)

原始查询具有以下声明:

 (SELECT DISTINCT a.id,b.item FROM Table1 a, Table1 b) a
Run Code Online (Sandbox Code Playgroud)

这是完整的笛卡尔积,然后做一个独特的.因此,如果您的表有100,000行,那么中间表有10,000,000,000行用于distinct(我不认为MySQL会更好地优化这一行).首先执行不同的操作(对于驱动程序)会大大减少数据量.

编辑:

有一类SQL问题,您需要查看两个或更多项的所有组合,然后确定每个人的值(即使数据中不存在的值)或查找不在数据中的值.这些问题带来了同样的问题:如何获得有关数据中不存在的值的信息?

我提倡的解决方案是创建一个包含所有可能组合的表,然后left [outer] join用于其余表.我称之为"驱动程序"表,因为此查询中的行通过定义后续连接的填充来"驱动"查询.

该术语与评论中的参考文献相当一致.评论使用优化程序角度的术语.一些连接算法 - 特别是嵌套循环和索引查找 - 以不同方式处理连接的两边; 对于这些,一方是"驾驶/司机"表.例如,当从大表连接到小型参考表时,大表是驱动表,而另一个表是通过索引访问的.其他连接算法 - 例如合并连接和散列连接(通常) - 对待双方都是相同的,因此概念在那里不太适用.

从逻辑角度来看,我用它来表示定义总体的查询.一个重要的相似之处在于,对于左/右外连接,两种定义在实践中是相同的.优化器通常会选择a中的第一个表left join作为"驱动程序",因为它定义了输出行.