【问题标题】:Count query is taking too long - over 24 hours have passed计数查询耗时过长 - 已超过 24 小时
【发布时间】:2013-08-01 14:19:34
【问题描述】:

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

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;

在这张桌子上:

ID         ITEM
-----------------
0001        345
0001        345
0001        120
0002        567
0002        034
0002        567
0003        567
0004        533
0004        008
...

为了得到这个结果:

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
...

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

谢谢

【问题讨论】:

  • 你添加了索引和键吗?
  • 您在 FROM 子句中运行的查询正在敲击数据库!您正在加入没有 where 条件的表,所以它本质上是对每条记录进行交叉连接,当有 400 万条记录时,这将需要很长时间!
  • 对不起,我是 mysql 新手,所以我不确定这是什么 - 所以答案是否定的......你能解释一下你的意思吗?
  • 您告诉数据库检查 400 万行和 400 万行。这意味着它必须进行 (4,000,000 * 4,000,000) = 16,000,000,000,000 次计算。不包括您进行的其他计算。
  • 请停止使用 MYSQL,直到您将学习基础知识....

标签: mysql sql database


【解决方案1】:

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

select id, item, count(*)
from Table1 a
group by id, item;

如果您希望显示所有 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;

原来的查询有这样的说法:

 (SELECT DISTINCT a.id,b.item FROM Table1 a, Table1 b) a

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

编辑:

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

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

这个术语与评论中的引用相当一致。该注释从优化器的角度使用该术语。一些连接算法——尤其是嵌套循环和索引查找——以不同的方式处理连接的两侧;对于这些,一侧是“驾驶/司机”表。例如,当从一个大表连接到一个小引用表时,大表是驱动表,另一个表是通过索引访问的。其他连接算法——例如合并连接和散列连接(通常)——将两边视为相同,因此该概念不太适用。

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

【讨论】:

  • “什么是驾驶台”asktom.oracle.com/pls/apex/… 您在稍微不同的环境中使用它。 +1 添加解释。
  • @JanDoggen 。 . .我试图在编辑后的评论中解释我的意思。
【解决方案2】:

如果您只想实现由iditem 分组的计数,您为什么不这样做:

SELECT ID, Item, COUNT(1)
FROM Table 1
GROUP BY ID, Item

就这么简单!

【讨论】:

  • 我也对计数为 0 的情况感兴趣
  • 这不是他想要的,看看 CNT 列中的 0:项目 8 和 34 出现在至少一个除 1 之外的其他 ID 中,因为 ID=1 他们的计数 = 0
【解决方案3】:

您的查询的速度问题可能是“不同的”,它在功能上选择所有数据、排序然后消除重复项,然后返回结果。 “Distinct”是一项昂贵的功能。

【讨论】:

    猜你喜欢
    • 2019-08-02
    • 1970-01-01
    • 2011-11-03
    • 2015-10-23
    • 2012-11-04
    • 2013-07-24
    • 2015-09-08
    • 2016-11-04
    相关资源
    最近更新 更多