如何优化sql查询

时间:2015-06-15 13:54:52

标签: sql sql-server

此查询在cg.ownerid IN(294777,228649,188464)的位置采用动态输入。当输入在IN条件下增加时,查询花费了太多时间来执行。请建议我优化它的方法。

例如,下面的查询需要4秒,如果我将列表缩小到IN(188464),它只需要1秒钟。

SELECT *
FROM
  (SELECT *,
          Row_number() OVER(
                            ORDER BY datecreated DESC) AS rownum
   FROM
     (SELECT DISTINCT c.itemid,
                      (CASE WHEN (Isnull(c.password, '') <> '') THEN 1 ELSE 0 END) AS password,
                      c.title,
                      c.encoderid,
                      c.type,
                      (CASE WHEN c.author = 'education' THEN 'Discovery' ELSE c.type END) AS TYPE,
                      c.publisher,
                      c.description,
                      c.author,
                      c.duration,
                      c.copyright,
                      c.rating,
                      c.userid,
                      Stuff(
                              (SELECT DISTINCT ' ' + NAME AS [text()]
                               FROM firsttable SUB
                               LEFT JOIN secondtable AS rgc ON thirdtable = rgc.id
                               WHERE SUB.itemid = c.itemid
                                 FOR xml path('')), 1, 1, '')AS [Sub_Categories]
      FROM fourthtable AS cg
      LEFT JOIN item AS c ON c.itemid = cg.itemid
      WHERE Isnull(title, '') <> ''
        AND c.active = '1'
        AND c.systemid = '20'
        AND cg.ownerid IN (294777,
                           228649,
                           188464)) AS a) AS b
WHERE rownum BETWEEN 1 AND 32
ORDER BY datecreated DESC

2 个答案:

答案 0 :(得分:2)

由于我还没有进一步的信息,我建议您先修改where子句。当您离开这些列时,应将它们移动到子查询。

SELECT *
FROM(
    SELECT *,
    Row_number() OVER(
    ORDER BY datecreated DESC) AS rownum
    FROM
    (SELECT DISTINCT c.itemid,
    (CASE WHEN (Isnull(c.password, '') <> '') THEN 1 ELSE 0 END) AS password,
    c.title,
    c.encoderid,
    c.type,
    (CASE WHEN c.author = 'education' THEN 'Discovery' ELSE c.type END) AS TYPE,
    c.publisher,
    c.description,
    c.author,
    c.duration,
    c.copyright,
    c.rating,
    c.userid,
    Stuff(
        (
            SELECT DISTINCT ' ' + NAME AS [text()]
            FROM firsttable SUB
            LEFT JOIN secondtable AS rgc ON thirdtable = rgc.id
            WHERE SUB.itemid = c.itemid
            FOR xml path('')
        ), 1, 1, ''
    ) AS [Sub_Categories]
    FROM (
        SELECT cg.itemid
        FROM fourthtable as cg
        WHERE cg.ownerid IN (294777,228649, 188464)
    ) AS cg
    LEFT JOIN (
        SELECT DISTINCT c.itemid, c.type, c.author, c.title, c.encoderid, c.type, c.publisher, c.description, c.author, c.duration, c.copyright, c.rating,c.userid
        FROM item as c
        WHERE Isnull(c.title, '') <> ''
        AND c.active = '1'
        AND c.systemid = '20'
    ) AS c 
        ON c.itemid = cg.itemid
    ) AS a
) AS b
WHERE rownum BETWEEN 1 AND 32
ORDER BY datecreated DESC

但不太确定是否所有内容都已立即连接,您遗漏了一些别名,这使我很难通过您的查询。但我知道你会得到我的想法。 : - )

答案 1 :(得分:0)

有了这些小信息,就无法给出任何具体的想法,但正常的一般情况适用:

  1. 启用统计信息io并检查导致大多数逻辑I / O的原因并尝试解决此问题
  2. 查看实际计划并检查是否有不合适的东西,例如:
    • 聚簇索引/表扫描(新索引可以解决此问题)
    • 包含大量行的键查找(向索引添加更多列可以解决此问题,无论是正常字段还是包含字段)
    • 线轴(新索引可以解决这个问题)
    • 估计行数与实际行数(10x,100x等)之间的巨大差异
  3. 为了给出更好的提示,你应该真正包括实际的计划,表格/索引结构至少在基本部分,并告诉什么是太多的时间(秒,分钟,小时?)