2015-02-03 3 views
1

У меня есть SQL-сервер 2008 года с большой таблицей, и мне нужно выполнить запрос COUNT DISTINCT на несколько столбцов вместе. Некоторые столбцы - varchar, а другие - int.Увеличение производительности при поиске в конкатенированных столбцах

Запрос до сих пор выглядит следующим образом:

SELECT 
    CAST(datepart(yyyy, [HistDate]) as varchar(4)) + '-' + CAST(datepart(mm, [HistDate]) as varchar(2)) + '-1' AS [DateSelector], 
    [Document] AS [Document], 
    -- This is the bit that needs optimizing 
    COUNT(DISTINCT(
    Document + 
    Reference + 
    CONVERT(varchar(20),BatchID) +    -- this is an int 
    ISNULL(CONVERT(varchar(20),ResetCount),'')) -- this is an int 
FROM documents 
GROUP BY 
    CAST(datepart(yyyy, [HistDate]) as varchar(4)) + '-' + CAST(datepart(mm, [HistDate]) as varchar(2)) + '-1' AS [DateSelector], 
    [Document] AS [Document], 
ORDER BY ... 

В настоящее время этот запрос занимает 23 сек, в то время как замена выше COUNT с COUNT (*) занимает несколько секунд. Я попытался добавить комбинированный индекс, который дал 0 улучшения. Какую оптимизацию можно сделать для ускорения поиска?

+0

Я бы предложил создать вычисляемый столбец для _DateSelector_ и индексации его. Но это также добавит накладные расходы для операций DML. Какова скорость изменения/поиска для таблицы? –

+0

@VishalGajjar, хотя это может немного помочь производительности, проблема с производительностью находится в другом месте кода в соответствии с вопросом и заголовком –

ответ

0

Вы, вероятно, может улучшить время с помощью

group by datepart(yyyy, Zeitstempel), datepart(mm, Zeitstempel) 

Вы можете сгруппировать на только целые числа без преобразования и по-прежнему использовать это в избранных.

+0

Хорошее мышление, но я боюсь, что не было улучшения ... –

+0

Я отредактировал свой ответ. К сожалению, раньше я вставил неправильный код. – Oliver

0

Конкатенация столбцов не улучшает производительность.

Попробуйте вместо этого:

;WITH CTE AS 
(
    SELECT 
    [HistDate], 
    [Document] AS [Document], 
    row_number() over (partition by Document, Reference + BatchID + ResetCount order by (select 1)) rn 
    FROM documents 
) 
SELECT 
    convert(char(8),dateadd(mm, 
    datediff(mm, 0, [HistDate]), 0), 126)+'1' AS [DateSelector], 
    [Document] AS [Document], 
    count(*) as cnt 
FROM CTE 
WHERE rn = 1 
GROUP BY 
    -- note you cant name a column in group by 
    dateadd(month, datediff(month, 0, [HistDate]), 0), 
    [Document] 
Смежные вопросы