简单的SQL查询需要20分钟才能运行?

时间:2014-08-21 14:49:00

标签: sql

我有一个查询根据总数输出百分比列表,我唯一想到的唯一部分是过滤'usid'等于另一个表上的值的有效方法。
查询没有失败,但需要很长时间才能完成。

    SELECT badge, count(usid)*100 / (SELECT COUNT(DISTINCT usid) from Table1)
    FROM Table1
    WHERE usid IN(
        SELECT usid
        FROM Table2
        WHERE msid = 1
        )
    GROUP BY badge

输出看起来像这样

    -----------------------------
    badge        count
    -----------------------------
    1            65.1
    2            45.4
    3            22.7
    4            12.12

它正在计算的usid我试图设置等于usid WHERE msid = 1。 即使这种方法有效,也需要太长时间。任何解决方案的想法?

4 个答案:

答案 0 :(得分:0)

您应该能够使用显式JOIN表示法而不是IN子句:

SELECT a.badge, COUNT(a.usid)*100 / (SELECT COUNT(DISTINCT usid) from Table1)
  FROM Table1 AS a
  JOIN (SELECT DISTINCT usid FROM Table2 WHERE msid = 1) AS b ON a.usid = b.usid
 GROUP BY a.badge

但是,我不相信会解决性能问题。一个中等体面的优化器会意识到select-list中的子选择是常量,但你应该通过查看查询计划来验证优化器是否正常(或更好)。

在这种情况下,我不相信COUNT(a.usid)COUNT(*)有任何不同之处。只有a.usid可以包含空值时,它才会产生不同的答案。另请参阅COUNT(*) vs COUNT(1) vs COUNT(pk) — which is better?

答案 1 :(得分:0)

这不是一个简单的查询。根据您使用的数据库,in可能效率很低,每个输出行都在计算count(distinct)。尝试将查询重写为:

SELECT badge, count(usid)*100 / x.cnt
FROM Table1 t1 cross join
     (SELECT COUNT(DISTINCT usid) as cnt from Table1) x
WHERE exists (select 1
              from table2 t2
              where t2.usid = t1.usid and t2.msid = 1
             )
GROUP BY t1.badge, x.cnt;

无论您使用何种数据库,此查询都可能更快。

顺便说一下,您计算count(usid)然后除以count(distinct usid)是可疑的。我希望这两者或两者都不是count(distinct)

答案 2 :(得分:0)

关于加速sql的一般经验法则:

  1. 仅返回所需的最少字段
  2. 使用分页 - 因此您提供偏移和限制,并获取数据页
  3. OR,上限以合理的截止值返回数据。 (您只会看到搜索的前500个结果,然后用户需要优化搜索参数)否则,有人可以运行开放式查询并对系统施加极大负荷。
  4. 避免IN语句
  5. 避免嵌套查询
  6. 在已加入/已搜索字段上添加索引(按查询中列出的顺序)
  7. 如果可能,请使用数字而不是字符串
  8. 如果不需要,请避免加入(您也可以对数据库进行非规范化)
  9. 如果可能的话,预计算信息(如总和)并将其存储在另一个表或字段中。这些可以在相关数据的插入/更新事件上更新。

答案 3 :(得分:0)

你可以试试这个:

declare @userIDcnt as int
select @userIDcnt = COUNT(DISTINCT usid) from Table1

SELECT badge, count(t1.usid)*100 / @userIDcnt
FROM Table1 t1
inner join Table2 t2 on t1.usid = t2.usid and t2.msid = 1
GROUP BY badge