выберите количество (*) против счетчика - PullRequest
4 голосов
/ 17 августа 2010

Предполагая, что индексы введены в действие, и абсолютная точность счета не требуется (допустимо отключение на один или два), можно ли использовать:

Опция A

select count(*) 
  from Table 
 where Property = @Property

против

Опция B

update PropertyCounters
   SET PropertyCount = PropertyCount + 1  
 where Property = @Property

затем выполняется:

select PropertyCount 
  from PropertyCounters 
 where Property = @Property

Насколько можно разумно ожидать снижения производительности от выполнения счетчика select (*) кактаблица превращается в тысячи / миллионы записей?

Ответы [ 5 ]

4 голосов
/ 17 августа 2010

Хранение отдельного столбца подсчета в дополнение к реальным данным является денормализацией.Существуют причины, по которым вам может потребоваться сделать это для повышения производительности, но вам не следует идти туда, пока вам это действительно не нужно.Это делает ваш код более сложным, с большей вероятностью появления несоответствий.

Для простого случая, когда запрос на самом деле просто SELECT COUNT(property) FROM table WHERE property=..., нет причин для денормализации;Вы можете сделать это быстро, добавив индекс к столбцу property.

3 голосов
/ 17 августа 2010

Вы не указали платформу, но поскольку вы используете синтаксис T-SQL для @variables, я рискну ответить на конкретный вопрос для платформы SQL Server:

count(*), или, строго говоря, будет count_big(*), является выражением, которое можно использовать в индексированных представлениях, см. Проектирование индексированных представлений .

create view vwCounts
with schembinding
as select Property, count_big(*) as Count
from dbo.Table
group by Property;

create unique clustered index cdxCounts on vwCounts(Property);

select Count 
from vwCount with (noexpand)
where Property = @property;

В Enterprise Edition оптимизатор будет даже использовать индексированное представление для исходного запроса:

select count_big(*)
from Table
where Property = @property;

Итак, в итоге вы получаете свой торт и едите его тоже: собственность уже собрана и поддерживается вашим двигателем бесплатно. Цена заключается в том, что обновления должны поддерживать индексированное представление (они будут , а не пересчитывать общее количество), а агрегация создаст горячие точки для конкуренции (блокировки в отдельных строках таблицы будут бороться за одинаковое количество (* ) обновление в индексированном представлении).

1 голос
/ 17 августа 2010

Если вы говорите, что вам не нужна абсолютная точность, тогда вариант Б - странный подход.Если вариант A становится слишком тяжелым (даже после добавления индексов), вы можете кэшировать выходные данные варианта A в памяти или в другой таблице (ваши PropertyCounters) и периодически обновлять его.

0 голосов
/ 17 августа 2010

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

С этим оператором SQL вы получите всеТаблицы в вашей базе данных и их количество строк, сохраняемое в SQL Server:

SELECT 
    t.NAME AS TableName,
    SUM(p.rows) AS RowCounts
FROM 
    sys.tables t
INNER JOIN      
    sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN 
    sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
WHERE 
    t.NAME NOT LIKE 'dt%' AND
    i.OBJECT_ID > 255 AND   
    i.index_id <= 1
GROUP BY 
    t.NAME, i.object_id, i.index_id, i.name 
ORDER BY 
    OBJECT_NAME(i.object_id) 

Я не смог найти никакой документации о том, насколько точно эти числа, как правило, - но, по моему собственному опыту, они 'обычно на месте (если вы не выполняете какую-либо массовую загрузку или что-то в этом роде - но в этом случае вам также не нужно постоянно сканировать таблицу, чтобы получить точное значение)

0 голосов
/ 17 августа 2010

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

Я бы сделал ставку на лучшую производительность в SQL Server, чем в Postgres, до такой степени, чтоЯ бы рассмотрел последний подход скорее на Postgres, а не на SQL Server.Тем не менее, с частичным индексом, точно подходящим для соответствия критериям, я бы поспорил на то, что Postgres победит SQL Server.Это только то, на что я поставил бы маленькие выигрыши, в любом случае я бы проверил, нужно ли мне думать об этом по-настоящему.

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

...