改进订单条款中的案例陈述

时间:2013-04-02 10:51:39

标签: sql sql-server tsql sql-server-2005

我有商店sql

ALTER procedure [dbo].[TNNews_User_SearchBasic]
    @Title nvarchar(400),
    @CategoryId int,
    @IsInterested int,
    @IsHot int,
    @IsTopCategory int,
    @IsPublish int,
    @PageSize int,
    @PageIndex int,
    @OrderBy varchar(20),
    @PortalId int,
    @LanguageId varchar(6)
as

DECLARE @EndTime   DATETIME
DECLARE @StartTime DATETIME
    SET @StartTime = GETDATE()

    declare @tbCategory table(Id int)
    DECLARE @StartRowIndex INT
    IF @PageSize=0 SELECT @PageSize=count(*) FROM TNNews
        IF(@PageIndex<0) SET @PageIndex=0
        SET @StartRowIndex = @PageSize*(@PageIndex-1)+1

    ;WITH tmpCategory(Id, Name,ParentId,Level)
    AS (
        SELECT 
            e.Id,
            e.Name,
            e.ParentId,
            1
        FROM dbo.TNCategory AS e
        WHERE 
        Id = @CategoryId or (@CategoryId='' and ParentId<=0)
        UNION ALL
        SELECT 
            e.Id,
            e.Name,
            e.ParentId,
            Level + 1
        FROM dbo.TNCategory AS e
        JOIN tmpCategory AS d ON e.ParentId = d.Id
        )
    insert @tbCategory select Id  from tmpCategory  

        ;WITH tmpNews as 
        (
            SELECT  
            a.Id,a.Title,a.Subject
            ,ROW_NUMBER() OVER (ORDER BY (Publisheddate) desc) as ThuTuBanGhi
            FROM dbo.TNNews a
            where 1 = 1
            --and ( Title like '%'+@Title+'%')
            and (@CategoryId = -1 or exists (select 0 from @tbCategory b where b.Id = a.CategoryId))
            and (@IsInterested = -1 or IsIntrested = @IsInterested )
            and (@IsHot = -1 or IsHot = @IsHot )
            and (@IsTopCategory = -1 or IsTopCategory = @IsTopCategory )
            and (@IsPublish = -1 or IsPublished = @IsPublish)
            and PortalId=@PortalId
            and LanguageId = @LanguageId
         )  
        select *, (select COUNT(Id) from tmpNews) as 'TongSoBanGhi' from tmpNews
        WHERE 
            ThuTuBanGhi BETWEEN (@StartRowIndex) AND (@StartRowIndex + @PageSize-1)


SET @EndTime = GETDATE()
PRINT 'StartTime = ' + CONVERT(VARCHAR(30),@StartTime,121)
PRINT '  EndTime = ' + CONVERT(VARCHAR(30),@EndTime,121)
PRINT ' Duration = ' + STR(DATEDIFF(MILLISECOND,@StartTime,@EndTime)) + ' millisecond'

select STR(DATEDIFF(MILLISECOND,@StartTime,@EndTime))

此商店执行后

EXEC    [dbo].[TNNews_User_SearchBasic]
        @Title='',
        @CategoryId = '',
        @IsInterested = -1,
        @IsHot = -1,
        @IsTopCategory = -1,
        @IsPublish = -1,
        @PageSize = 20,
        @PageIndex = 1,
        @OrderBy = '',
        @PortalId = 0,
        @LanguageId = N'vi-VN'

go

时间约为“200ms”。我创建了一个新的商店“TNNews_User_SearchBasic1”并进行了一些更改。

.....
--,ROW_NUMBER() OVER (ORDER BY (Publisheddate) desc) as ThuTuBanGhi
,ROW_NUMBER() OVER (ORDER BY (case when @OrderBy='VIEW_COUNT' then ViewCount else PublishedDate end) desc) as ThuTuBanGhi
.....

现在是执行此商店的时间

EXEC    [dbo].[TNNews_User_SearchBasic1]
        @Title='',
        @CategoryId = '',
        @IsInterested = -1,
        @IsHot = -1,
        @IsTopCategory = -1,
        @IsPublish = -1,
        @PageSize = 20,
        @PageIndex = 1,
        @OrderBy = '',
        @PortalId = 0,
        @LanguageId = N'vi-VN'

GO
大约900毫秒。 我不明白为什么会有变化。请帮我改进这些商店。

PS:我将示例数据库放在:http://anhquan22.tk/Portals/0/Videos/web.rar

1 个答案:

答案 0 :(得分:0)

完成分析数据库的结构。问题的一部分隐藏在表结构中。 我为你准备了备份。在其中,我稍微修改了方案以提高性能并对表进行规范化。您可以从this link下载。

...对于你的问题,我会这样做 -

DECLARE @SQL NVARCHAR(1000)
SELECT @SQL = N'
;WITH tmpCategory (Id, Name, ParentId, [Level]) AS 
(
 SELECT
   e.Id
 , e.Name
 , e.ParentId
 , 1
 FROM dbo.TNCategory e
 WHERE Id = @CategoryId OR (@CategoryId = '''' AND ParentId <= 0)

 UNION ALL

 SELECT
   e.Id
 , e.Name
 , e.ParentId
 , [Level] + 1
 FROM dbo.TNCategory e
 JOIN tmpCategory d ON e.ParentId = d.Id
)
SELECT 
   a.Id
 , ROW_NUMBER() OVER (ORDER BY ' + 
   CASE WHEN @OrderBy = 'VIEW_COUNT' 
    THEN 'ViewCount' 
    ELSE 'PublishedDate'
   END +' DESC) AS ThuTuBanGhi
FROM dbo.TNNewsMain a
where PortalId = @PortalId 
 AND LanguageId = @LanguageId'
 + CASE WHEN @IsInterested != -1 THEN ' AND IsInterested = @IsInterested' ELSE '' END
 + CASE WHEN @IsHot != -1 THEN ' AND IsHot = @IsHot' ELSE '' END
 + CASE WHEN @IsTopCategory != -1 THEN ' AND IsTopCategory = @IsTopCategory' ELSE '' END
 + CASE WHEN @IsPublish != -1 THEN ' AND IsPublish = @IsPublish' ELSE '' END
 + CASE WHEN @CategoryId != -1 THEN '' ELSE ' AND EXISTS(SELECT 1 FROM tmpCategory b WHERE b.Id = a.CategoryId)' END

INSERT INTO @temp (Id, ThuTuBanGhi)
EXECUTE sp_executesql 
@SQL
, N'@PortalId INT
, @LanguageId VARCHAR(6)
, @CategoryId INT
, @IsInterested INT
, @IsHot INT
, @IsTopCategory INT
, @IsPublish INT'
, @PortalId = @PortalId
, @LanguageId = @LanguageId
, @CategoryId = @CategoryId
, @IsInterested = @IsInterested
, @IsHot = @IsHot
, @IsTopCategory = @IsTopCategory
, @IsPublish = @IsPublish;

SELECT 
  d.Id
, tm.Title
, tm.[Subject]
, d.ThuTuBanGhi
, c.TongSoBanGhi
FROM (
SELECT  t.Id
 , t.ThuTuBanGhi
FROM @temp t
WHERE t.ThuTuBanGhi BETWEEN @StartRowIndex AND @StartRowIndex + @PageSize - 1
) d 
JOIN TNNewsMain tm ON d.Id = tm.Id
CROSS JOIN (
SELECT TongSoBanGhi = (SELECT COUNT(1) FROM @temp)
) c