2016-06-13 3 views
3

Это запрос, у меня естьSQL Server: Производительность графа() с тем, где пункт

SELECT COUNT(*) 
FROM tbl 
WHERE intCol = @intval 
    AND varcharCol = @varchr 
    AND (datetimeCol BETWEEN @from AND @to) 

Запрос принимает 20 секунд на столе с 6 миллионов записей. Это очень плохо для меня, поскольку данные могут быть в 20 раз больше. Есть ли способ сделать это быстрее?

У меня есть комбинированный индекс в месте на (intCol, varcharCol, datetimeCol) и план выполнения показывает сканирование индекса (cost 91%) ->stream aggregate (cost 9%) -> Compute Scalar (cost 0%)

высоко ценит помощь

+0

Рассмотрим индексированных View http://aboutsqlserver.com/2011/03/24/indexed-materialized-views-in-microsoft-sql-server/ – Bas

+0

Сначала вы могли бы попытаться поставить индекс на один ** непустой номер ** 'int' (что-то вроде вашего ** первичного ключа ** -' ID' или что-то еще). Поскольку это всего лишь один 4-байтовый 'int', индекс будет требовать меньше страниц для чтения только для определения количества строк. Или вы можете использовать представления системного каталога, чтобы получить ** приблизительный ** подсчет строки в вашей таблице. –

+0

В зависимости от вашей версии SQL Server вы также можете рассмотреть индекс хранилища столбцов, который бы помог, особенно учитывая, что часть диапазона дат Ваш запрос. –

ответ

0

Заменить счетчик (@TheIDOfyourTable)

+0

Это не будет быстрее, чем 'SELECT COUNT (*)', если только в столбце 'TheIDOfourTable' нет отдельного некластеризованного индекса .... –

0

Простое использование этой строки кода для быстрого подсчета

SELECT  count(1) 
FROM   tbl 
+0

Это не будет быстрее, чем 'SELECT COUNT (*)' ...... –

3

Могу ли я спросить, какие типы данных находятся в вашей таблице? Кроме того, какой тип машины вы используете?

Не похоже, чтобы что-то складывалось. Я придумал некоторые тестовые данные и выполнил запрос выше, и запрос выполняется почти мгновенно, даже при работе с maxdop 1.

Вот мой тест данные:

create table dbo.tbl (
    intCol int, 
    varcharCol varchar(128), 
    datetimeCol datetime); 

insert tbl (
    intCol, 
    varcharCol, 
    datetimeCol) 
select top (6000000) 
    abs(checksum(newid())) % 100, 
    abs(checksum(newid())) % 100, 
    convert(datetime, abs(checksum(newid())) % 50000) 
from sys.all_columns a 
cross join sys.all_columns b; 

create nonclustered index uc 
    on tbl (intCol, varcharCol, datetimeCol); 

Ниже вы можете выбрать любую комбинацию цифр, пока они находятся в пределах области допустимых значений, и вы почти гарантированные матчи, так как размер данных набор является существенным.

declare 
    @intval int = 50, 
    @varchr varchar(128) = '55', 
    @from datetime = '1900-01-01', 
    @to datetime = '1950-01-01'; 

set nocount on; 
set statistics io on; 
set statistics time on; 

select count(*) -- select * 
from tbl 
where intCol = @intval 
    and varcharCol = @varchr 
    and datetimeCol between @from and @to 
option (maxdop 1); 

set statistics time off; 
set statistics io off; 

Результаты показывают, что время выполнения - это de minimis.

 
----------- 
221 

Table 'tbl'. Scan count 1, logical reads 5, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 


SQL Server Execution Times: 
    CPU time = 0 ms, elapsed time = 0 ms. 

Кроме того, план запроса, который я вижу, аналогичен тому, что вы упомянули в своем оригинальном посте. Это типичный план выполнения и стоимость простого запроса с агрегированием и предложением where.

Query Cost

+0

Прежде чем перейти на использование индекса хранилища столбцов, выполняете ли вы эти тесты с машины разработки или вашего локального окна? Просто интересно, можете ли вы столкнуться с ограничениями памяти, и ваша машина использует виртуальную память, то есть подкачку и т. Д. Я сомневаюсь, что SQL Server не отвечает потребностям этого запроса, учитывая правильную среду. Это точно тот тип, который SQL предназначен для очень хорошо. – Yobik

+0

Спасибо за ответ Yobik, я делаю это на машине для разработки, у вас 4GB-фиксация с физической памятью 8 ГБ. Запрос выполняется почти мгновенно во второй раз, возможно, из-за кеша. Мне интересно, как он работает так быстро для вас. Можете ли вы попробовать запустить DBCC DROPCLEANBUFFERS перед запуском запроса. Это должно очистить кеш – Balok

+0

Balok - я просто запускал это на другой машине разработки и согласен с другой областью разработки, которую я запускал ранее, например. 'Истекшее время = 2 мс'. Кроме того, запустил его с помощью 'dbcc dropcleanbuffers;' перед выполнением запроса и получением аналогичных результатов. btw - первая коробка разработки имеет SSD, а вторая использует шпиндели. – Yobik

Смежные вопросы