2016-08-17 5 views
-2

Есть два запроса ниже, которые возвращают количество столбцов идентификатора, исключая значения NULL , а второй запрос возвращает количество всех строк из таблицы, включая строки NULL.Разница в производительности между Select count (ID) и Select count (*)

select COUNT(ID) from TableName 

select COUNT(*) from TableName 

Мой Путаница: Есть ли разница в производительности?

+0

Логика указывает на то, что тест для NULL замедлит работу - разница, вероятно, в миллисекундах, если у вас нет миллионов записей. – rheitzman

+0

@ Kamil: Хотя похоже, это не тот же вопрос. Ваша ссылка связана с тремя различными способами выражения запроса, которые будут генерировать точные результаты. В этом случае 2 запроса не возвращают те же результаты. Основываясь на описании OP, 'ID' имеет значение NULL, что очень странно. Я надеюсь, что описание OP верное. – sstan

+0

Каково определение 'TableName'? Является ли 'ID' действительно нулевым, как вы предлагаете? Нечетное имя, если оно есть. Какие индексы у вас есть? – sstan

ответ

1

TL/DR: планы не могут быть таким же, вы должны проверить на соответствующих данных и убедитесь, что у вас есть правильные индексы, а затем выбрать оптимальное решение на основе ваших исследований.

Планы запросов могут отличаться в зависимости от индексации и нулевой точности столбца, который используется в функции COUNT.

В следующем примере я создаю таблицу и заполняю ее миллионом строк. Все столбцы были проиндексированы за исключением столбца 'b'.

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

Это было протестировано на SQL Server 2014, у меня нет доступа к экземпляру 2012 года в данный момент. Вы должны проверить это самостоятельно, чтобы найти лучшее решение.

create table t1(id bigint identity, 
       dt datetime2(7) not null default(sysdatetime()), 
       a char(800) null, 
       b char(800) null, 
       c char(800) null); 

-- We will use these 4 indexes. Only column 'b' does not have any supporting index on it. 
alter table t1 add constraint [pk_t1] primary key NONCLUSTERED (id); 
create clustered index cix_dt on t1(dt); 
create nonclustered index ix_a on t1(a); 
create nonclustered index ix_c on t1(c); 

insert into T1 (a, b, c) 
select top 1000000 
    a = case when low = 1 then null else left(REPLICATE(newid(), low), 800) end, 
    b = case when low between 1 and 10 then null else left(REPLICATE(newid(), 800-low), 800) end, 
    c = case when low between 1 and 192 then null else left(REPLICATE(newid(), 800-low), 800) end 
from master..spt_values 
cross join (select 1 from master..spt_values) m(ock) 
where type = 'p'; 


checkpoint; 

-- All rows, no matter if any columns are null or not 
-- Uses primary key index 
select count(*) from t1; 

-- All not null, 
-- Uses primary key index 
select count(id) from t1; 

-- Some values of 'a' are null 
-- Uses the index on 'a' 
select count(a) from t1; 

-- Some values of b are null 
-- Uses the clustered index 
select count(b) from t1; 

-- No values of dt are null and the table have a clustered index on 'dt' 
-- Uses primary key index and not the clustered index as one could expect. 
select count(dt) from t1; 

-- Most values of c are null 
-- Uses the index on c 
select count(c) from t1; 

Different select count results

Теперь, что бы произошло, если бы мы были более четко в том, что мы хотели, чтобы наш счет сделать? Если мы скажем планировщику запросов, что хотим получить только строки, которые не имеют значения null, это что-то изменит?

-- Homework! 
-- What happens if we explicitly count only rows where the column is not null? What if we add a filtered index to support this query? 
-- Hint: It will once again be different than the other queries. 
create index ix_c2 on t1(c) where c is not null; 
select count(*) from t1 where c is not null; 
Смежные вопросы