如何加快查询速度?

时间:2014-11-26 13:08:45

标签: sql-server

这是我的查询(它是存储过程的一部分):

declare @sql varchar(4000)
declare @tab1 table (ActionID int, ActionDate datetime, [Group] varchar(10), GroupUnicode int, GroupList varchar(100), Artist varchar(250), PlaceName varchar(250),
    ActionType varchar(25), ActionTypeID smallint, ActionPlaceID int, Picture varchar(512), SearchWords varchar(250), ActionEndDate datetime, StrEndDate varchar(250),
    NameForH1 nvarchar(1000), DatesAsPeriod tinyint, DateList varchar(4000))

set @Date2 = DATEADD(day, 1, @Date2)
    insert into @tab1(ActionID, ActionDate, Artist, PlaceName, ActionTypeID, ActionPlaceID, SearchWords, ActionEndDate, StrEndDate, NameForH1, DatesAsPeriod, DateList)
    select X.ID, convert(datetime, SUBSTRING(X.DateList, 1, 19), 120), X.Artist, PlaceName, X.ActionTypeID, X.ActionPlaceID, X.SearchWords, ActionEndDate,
        case when ActionEndDate IS NOT NULL AND convert(datetime, SUBSTRING(X.DateList, 1, 19), 120) < ActionEndDate 
        then ' - ' + convert(varchar, ActionEndDate, 104) + ' ' + convert(varchar(5), ActionEndDate, 108)
        else '' end as StrEndDate, X.NameFOrH1, X.DatesAsPeriod, X.DateList
    from (
        SELECT DISTINCT 
         TOP (100) PERCENT a.ID, a.Artist, a.DateBeg, a.DateEnd, ap.PlaceName, a.ProviderID, a.SubSiteID, a.ActionPlaceID,
         a.CounterAgentID, a.ActionTypeID, a.GenreTypeID, a.ShowTypeID AS ActionShowTypeID, ad.ShowTypeID, ap.CityID, a.ActionPlaceGroupID, 
         a.ActionTopTypeID, a.Canceled, a.ETicketEnabled, st.ShowOnMainPage AS ActionShowOnMainPage, st.ShowInActionList AS ActionShowInActionList, 
         st.ShowInCashdesk AS ActionShowInCashdesk, st1.ShowOnMainPage, st1.ShowInActionList, st1.ShowInCashdesk, a.SearchWords, a.AutoGenerate, 
         ad.ActionEndDate, a.NameForH1, a.CommonActionId, tca.Name AS CommonActionName, a.AgeRestrictionsId, a.DatesAsPeriod,
         dbo.fn_ConvertActionDatesToDateList(a.ID) AS DateList
        FROM dbo.T_Action AS a INNER JOIN
         dbo.T_ActionDates AS ad ON a.ID = ad.ActionID INNER JOIN
         dbo.T_ActionPlace AS ap ON a.ActionPlaceID = ap.ID INNER JOIN
         dbo.T_ShowType AS st ON a.ShowTypeID = st.ID LEFT OUTER JOIN
         dbo.T_ShowType AS st1 ON ad.ShowTypeID = st1.ID LEFT OUTER JOIN                                        
         dbo.T_CommonAction AS tca ON tca.ID = a.CommonActionId
        WHERE (a.Visible = 1)) AS X INNER JOIN dbo.T_Action AS a ON X.ID = a.ID    
where (ActionShowInActionList = 1) and (ShowInActionList = 1)
    and ((X.Artist like '%' + @Artist + '%') or (X.SearchWords like '%' + @Artist + '%'))
    and X.ActionTypeID = case when @ActionTypeID > 0 then @ActionTypeID else X.ActionTypeID end 
    and X.ActionTopTypeID = case when @ActionTopTypeID > 0 then @ActionTopTypeID else X.ActionTopTypeID end 
    and X.GenreTypeID = case when @GenreTypeID > 0 then @GenreTypeID else X.GenreTypeID end 
    and X.ActionPlaceID = case when @ActionPlaceID > 0 then @ActionPlaceID else X.ActionPlaceID end
    and CityID = case when @CityID > 0 then @CityID else CityID end
    and X.ActionPlaceGroupID = case when @GroupPlaceID > 0 then @GroupPlaceID else X.ActionPlaceGroupID end
    and ((convert(datetime, SUBSTRING(X.DateList, 1, 19), 120) = '1980-01-01') 
    or   ((convert(datetime, SUBSTRING(X.DateList, 1, 19), 120) >= @Date1 OR ActionEndDate >= @Date1) AND convert(datetime, SUBSTRING(X.DateList, 1, 19), 120) < @Date2))
order by
    case when @SortBy = 'byPlace' then PlaceName end,
    case when @SortBy = 'byDate' or @SortBy = 'byPlace' then case when convert(datetime, SUBSTRING(X.DateList, 1, 19), 120) = '1980-01-01 00:00' then DATEADD(YY, 1000, convert(datetime, SUBSTRING(X.DateList, 1, 19), 120)) else convert(datetime,            SUBSTRING(X.DateList, 1, 19), 120) end end, Artist, 
    case when @SortBy = 'byAlphabet' then convert(datetime, SUBSTRING(X.DateList, 1, 19), 120) end

如您所见,存在嵌套查询,并且存在以下结构:

convert(datetime, SUBSTRING(X.DateList, 1, 19), 120)

重复几次。

此外,还有函数dbo.fn_ConvertActionDatesToDateList(a.ID):

ALTER FUNCTION [fn_ConvertActionDatesToDateList]
(
   @actionId     int
)
RETURNS varchar(4000)
AS
BEGIN
   declare @dateList varchar(4000)

   select distinct @dateList = STUFF(CAST((
      SELECT [text()] = ', ' + convert(varchar, ActionDate, 120)
      FROM T_ActionDates where ActionID = a.ID and (ActionDate = '1980-01-01' or ActionDate > GETDATE())
      FOR XML PATH(''), TYPE) AS VARCHAR(8000)), 1, 2, '') from T_Action as a join T_ActionDates as ad on a.ID = ad.ActionID
      where (ad.ActionDate = '1980-01-01' or ad.ActionDate > GETDATE()) and Visible = 1 and CloseForCorrect = 0 and a.ID = @actionId

   return @dateList
END

如何加快速度?

1 个答案:

答案 0 :(得分:0)

我真的无法确切地告诉你如何解决这个问题,但我可以指出几乎肯定会导致减速的斑点。

  1. 确保索引所有连接和WHERE子句中的列。除非你告诉我们,否则这里的任何人都无法知道什么是索引,也没有索引。
  2. 子选择有TOP (100) PERCENT。你不应该这样。
  3. 通过子选择而不改进子选择中的WHERE子句,您正在生成可能较大的数据子集。看起来主要选择中的WHERE应该移动到子选择中。
  4. 摆脱子选择。
  5. 说完这些话,试试这个:

    declare @sql varchar(4000)
    declare @tab1 table (ActionID int, ActionDate datetime, [Group] varchar(10), GroupUnicode int, GroupList varchar(100), Artist varchar(250), PlaceName varchar(250),
    ActionType varchar(25), ActionTypeID smallint, ActionPlaceID int, Picture varchar(512), SearchWords varchar(250), ActionEndDate datetime, StrEndDate varchar(250),
    NameForH1 nvarchar(1000), DatesAsPeriod tinyint, DateList varchar(4000))
    
    set @Date2 = DATEADD(day, 1, @Date2)
    
    insert into @tab1(ActionID, ActionDate, Artist, PlaceName, ActionTypeID, ActionPlaceID, SearchWords, ActionEndDate, StrEndDate, NameForH1, DatesAsPeriod, DateList)
        select
            X.ID, convert(datetime, SUBSTRING(X.DateList, 1, 19), 120), X.Artist, PlaceName, X.ActionTypeID, X.ActionPlaceID, X.SearchWords, ActionEndDate,
            case
                when ActionEndDate IS NOT NULL AND convert(datetime, SUBSTRING(X.DateList, 1, 19), 120) < ActionEndDate 
                    then ' - ' + convert(varchar, ActionEndDate, 104) + ' ' + convert(varchar(5), ActionEndDate, 108)
                else ''
            end as StrEndDate
            , X.NameFOrH1, X.DatesAsPeriod, X.DateList
        from (
            SELECT DISTINCT
                a.ID, a.Artist, a.DateBeg, a.DateEnd, ap.PlaceName, a.ProviderID, a.SubSiteID, a.ActionPlaceID,
                a.CounterAgentID, a.ActionTypeID, a.GenreTypeID, a.ShowTypeID AS ActionShowTypeID, ad.ShowTypeID, ap.CityID, a.ActionPlaceGroupID, 
                a.ActionTopTypeID, a.Canceled, a.ETicketEnabled, st.ShowOnMainPage AS ActionShowOnMainPage, st.ShowInActionList AS ActionShowInActionList, 
                st.ShowInCashdesk AS ActionShowInCashdesk, st1.ShowOnMainPage, st1.ShowInActionList, st1.ShowInCashdesk, a.SearchWords, a.AutoGenerate, 
                ad.ActionEndDate, a.NameForH1, a.CommonActionId, tca.Name AS CommonActionName, a.AgeRestrictionsId, a.DatesAsPeriod,
                dbo.fn_ConvertActionDatesToDateList(a.ID) AS DateList
            FROM dbo.T_Action AS a
            INNER JOIN dbo.T_ActionDates AS ad ON a.ID = ad.ActionID
            INNER JOIN dbo.T_ActionPlace AS ap ON a.ActionPlaceID = ap.ID
            INNER JOIN dbo.T_ShowType AS st ON a.ShowTypeID = st.ID
            LEFT OUTER JOIN dbo.T_ShowType AS st1 ON ad.ShowTypeID = st1.ID
            LEFT OUTER JOIN dbo.T_CommonAction AS tca ON tca.ID = a.CommonActionId
            WHERE a.Visible = 1
            AND ActionShowInActionList = 1
            and (ShowInActionList = 1)
            and (
                    (Artist like '%' + @Artist + '%')
                or  (SearchWords like '%' + @Artist + '%')
            )
            and ActionTypeID = case when @ActionTypeID > 0 then @ActionTypeID else ActionTypeID end 
            and ActionTopTypeID = case when @ActionTopTypeID > 0 then @ActionTopTypeID else ActionTopTypeID end 
            and GenreTypeID = case when @GenreTypeID > 0 then @GenreTypeID else GenreTypeID end 
            and ActionPlaceID = case when @ActionPlaceID > 0 then @ActionPlaceID else ActionPlaceID end
            and CityID = case when @CityID > 0 then @CityID else CityID end
            and ActionPlaceGroupID = case when @GroupPlaceID > 0 then @GroupPlaceID else ActionPlaceGroupID end
            and (
                convert(datetime, SUBSTRING(DateList, 1, 19), 120) = '1980-01-01'
                or  (
                        (
                                convert(datetime, SUBSTRING(DateList, 1, 19), 120) >= @Date1
                            OR  ActionEndDate >= @Date1
                        )
                        AND convert(datetime, SUBSTRING(DateList, 1, 19), 120) < @Date2
                    )
            )
        ) AS X
        order by
        case when @SortBy = 'byPlace' then PlaceName end,
        case when @SortBy = 'byDate' or @SortBy = 'byPlace' then case when convert(datetime, SUBSTRING(X.DateList, 1, 19), 120) = '1980-01-01 00:00' then DATEADD(YY, 1000, convert(datetime, SUBSTRING(X.DateList, 1, 19), 120)) else convert(datetime,            SUBSTRING(X.DateList, 1, 19), 120) end end, Artist, 
        case when @SortBy = 'byAlphabet' then convert(datetime, SUBSTRING(X.DateList, 1, 19), 120) end
    
相关问题