【问题标题】:How to optimize nested query如何优化嵌套查询
【发布时间】:2010-11-25 11:33:29
【问题描述】:

我有很多这样的查询:

     select  thread_id as topic_id,title as topic            
  ,            
    isnull((select count(*) from tblmessages b where thread_id=a.thread_id and is_approved='Y' and sort_level>1            
     group by b.thread_id            
     ),0) as replies,            
    isnull((select count(*) from tblmessages b where thread_id=a.thread_id and isnull(new_post,'Y')='Y' and sort_level>1            
     group by b.thread_id            
     ),0) as NewPost,            
    isnull((select count(*) from tblmessages b where thread_id=a.thread_id and isnull(is_approved,'N')='N' and sort_level>1            
     group by b.thread_id            
     ),0) as NotClear,            

    sort_level,sort_index,  from tblMessages a            
    where   sort_level=1 and category=@category 
    order by topic_id desc

请告诉我如何优化和更好地编写此类查询。因为我有记录 5,00,000 的表。所以这需要很多时间,而且有时会超时。

谢谢

【问题讨论】:

  • 那是 500 万条还是 5000 万条记录?

标签: sql sql-server-2005 query-optimization


【解决方案1】:

您应该将各种子查询分组到一个具有不同计数的单个子查询中,并使用连接将数据放在一起

子查询应该是:

select thread_id
     count(when isnull(is_approved,'N')='N' then 1 end) as replies,
     count(when isnull(new_post,'Y')='Y' then 1 end) as NewPost,
     count(when isnull(is_approved,'N')='N' then 1 end) as NotClear
     from tblmessages 
     where sort_level>1  
     group by thread_id

虽然最终查询如下

select  thread_id as topic_id,title as topic,
   sort_level,sort_index , B.replies, B.NewPost, B.NotClear
   from tblMessages a            
   join
     (select thread_id
     count(when isnull(is_approved,'N')='N' then 1 end) as replies,
     count(when isnull(new_post,'Y')='Y' then 1 end) as NewPost,
     count(when isnull(is_approved,'N')='N' then 1 end) as NotClear
     from tblmessages 
     where sort_level>1  
     group by thread_id) as B
     on a.thread_id = B.thread_id
    where   sort_level=1 and category=@category 
    order by topic_id desc

【讨论】:

  • @il_guru_ji: gr8.. 感谢这提高了我的查询性能。
【解决方案2】:

你可以尝试去规范化一点:

  1. 创建repliesNewPostNotClear 字段
  2. 编写一个更新这些字段的例程,cron 它(周期取决于 3。)
  3. 重写影响这些字段的大多数/所有查询以更新它们。如果你重写所有,运行 2. 一天几次。否则,根据您需要的数据完整性,每小时执行几次。

这显然有助于您的查询。但是,它需要更多的维护,因为几乎从未使用过的任何小查询都会破坏一致性(想想一些针对 BB 的调节工具,例如拆分主题......)

【讨论】:

    【解决方案3】:
    SELECT a.* 
    FROM 
        (SELECT   
            thread_id AS topic_id,
            title AS topic ,
            SUM(CASE WHEN is_approved='Y' AND sort_level > 1 THEN 1 ELSE 0 END) as replies, 
            SUM(CASE WHEN isnull(new_post,'Y')='Y' AND sort_level > 1 THEN 1 ELSE 0) END as NewPost, 
            SUM(CASE WHEN isnull(is_approved,'N')='N' AND sort_level > 1 THEN 1 ELSE 0 END) as NotClear, 
            sort_level ,
            sort_index,  
            category ,
            topic_id
        FROM 
            tblMessages 
        ) a
    WHERE 
        a.sort_level=1 AND a.category=@category 
    ORDER BY 
            a.topic_id DESC
    

    我无法对此进行测试,所以可能存在一些语法错误,但你明白了吗?

    【讨论】:

    • 您需要对 SUM 的嵌套查询进行分组
    猜你喜欢
    • 2018-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多