当前位置: 代码迷 >> Sql Server >> 话语优化-高手请指点
  详细解决方案

话语优化-高手请指点

热度:76   发布时间:2016-04-24 18:25:12.0
语句优化---高手请指点
求大神指点,下面的语句,是否有优化空间(注:索引已调整到最佳),可否从语句写法方面入手:

SELECT
       u.username,
       u.userid,
       u.province,
       u.dotadmin,
       t.tickets,
       u.viplevel,
       u.regdata,
       u.maintainlevel,
       d.staffname,
       d.staffid
  FROM subsidiaryreportsystem.dbo.distributorstaffmapping d WITH (NOLOCK)
       LEFT JOIN subsidiaryreportsystem.dbo.tbluser u WITH (NOLOCK)
          ON d.userid = u.userid
       LEFT JOIN
       (
SELECT userid, sum (ticketnums) tickets
FROM subsidiaryreportsystem.dbo.ticketmonitor WITH (NOLOCK)
WHERE date > '2014-2-1 0:00:00' AND date < '2014-2-28 23:59:59'
GROUP BY userid
) t
          ON d.userid = t.userid
       LEFT JOIN subsidiaryreportsystem.dbo.tblspecialuser s WITH (NOLOCK)
          ON s.userid = d.userid
 WHERE     s.userid IS NULL
       AND u.admin = 1
       AND d.staffid = 318924
       AND u.province = '江苏'
ORDER BY tickets DESC

我做了如下更改(使用子查询,去掉了s表的连接),执行计划是少了很多,但是效率基本没变:

SELECT TOP 100
u.username,
    u.userid,
    u.province,
    u.dotadmin,
    t.tickets,
    u.viplevel,
    u.regdata,
    u.maintainlevel,
    d.staffname,
    d.staffid
from
(
select 
userid,
staffname,
staffid
FROM 
subsidiaryreportsystem.dbo.distributorstaffmapping WITH (NOLOCK)
where 
staffid = 318924
) d
inner join
(
select
username,
userid,
province,
dotadmin,
viplevel,
regdata,
maintainlevel
from
subsidiaryreportsystem.dbo.tbluser WITH (NOLOCK)
where 
admin = 1
AND province = '江苏'
) u
on d.userid=u.userid
left join
(
SELECT 
userid, 
sum (ticketnums) tickets
FROM 
subsidiaryreportsystem.dbo.ticketmonitor WITH (NOLOCK)
WHERE 
date > '2014-02-01 0:00:00' AND date < '2014-02-28 23:59:59'
GROUP BY userid
) t
ON d.userid = t.userid
order by tickets

------解决方案--------------------
很正常的语句,在语句上应该没有太大的改善空间了,还是考虑下索引,如果允许的话用一些带include的大索引,还有就是

SELECT userid, sum (ticketnums) tickets
 FROM subsidiaryreportsystem.dbo.ticketmonitor WITH (NOLOCK)
WHERE date > '2014-2-1 0:00:00' AND date < '2014-2-28 23:59:59'
 GROUP BY userid

这个聚合可以先计算存储到一个表,一段时间内做一次增量或者全量的更新,然后使用这个表做查询。
------解决方案--------------------
    SELECT 
        userid, 
        sum (ticketnums) tickets
    FROM 
        subsidiaryreportsystem.dbo.ticketmonitor WITH (NOLOCK)
    WHERE 
        date > '2014-02-01 0:00:00' AND date < '2014-02-28 23:59:59'
    GROUP BY userid


这个过滤了还有10W啊?
------解决方案--------------------
初步结果:
1、你的TicketMonitor表索引不合理,先加这个:
USE [SubsidiaryReportSystem]
GO
CREATE NONCLUSTERED INDEX IX_TicketMonitor_Include
ON [dbo].[TicketMonitor] ([Date])
INCLUDE ([UserID],[TicketNums])
GO
2、TicketMonitor这个表的聚集索引放到一个没用到的ID列上,单纯从这个语句来看比较浪费,PK可以设在ID上,不过聚集索引可以考虑移开。比如移到userid上。
3、你的表TicketMonitor有没有做分区?如果没有,在上面两步做完还没比较明显的改进后,可以按月分区
  相关解决方案