Подтвердить что ты не робот

Показатель SQL count (*)

У меня есть таблица SQL BookChapters с более чем 20 миллионами строк. Он имеет кластерный первичный ключ (bookChapterID) и не имеет других ключей или индексов. Требуется miliseconds для запуска следующего запроса

if (select count(*) from BookChapters) = 0
...

Однако, это занимает более 10 минут, когда я меняю его так

if (select count(*) from BookChapters) = 1
...

или

if (select count(*) from BookChapters) > 1
...

Почему? Как я могу получить select count(*) для выполнения быстрее?

4b9b3361

Ответ 1

У Mikael Eriksson есть хорошее объяснение, почему первый запрос выполняется быстро:

SQL-сервер оптимизирует его: if exists(select * from BookChapters). Поэтому он ищет наличие одной строки вместо подсчета всех строк в таблице.

Для двух других запросов SQL Server будет использовать следующее правило. Чтобы выполнить запрос типа SELECT COUNT(*), SQL Server будет использовать самый узкий некластеризованный индекс для подсчета строк. Если в таблице нет некластеризованный индекс, ему придется сканировать таблицу.

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

--SQL Server 2005/2008
SELECT OBJECT_NAME(i.id) [Table_Name], i.rowcnt [Row_Count]
FROM sys.sysindexes i WITH (NOLOCK)
WHERE i.indid in (0,1)
ORDER BY i.rowcnt desc

--SQL Server 2000
SELECT OBJECT_NAME(i.id) [Table_Name], i.rows [Row_Count]
FROM sysindexes i (NOLOCK)
WHERE i.indid in (0,1)
ORDER BY i.rows desc

Он использует системную таблицу sysindexes. Дополнительная информация вы можете найти здесь SQL Server 2000, SQL Server 2005, SQL Server 2008, SQL Server 2012

Вот еще одна ссылка Почему мой SELECT COUNT (*) работает так медленно? с другим решением. Он показывает технику, которую Microsoft использует для быстрого отображения количества строк при щелчке правой кнопкой мыши по таблице и выборе свойств.

select sum (spart.rows)
from sys.partitions spart
where spart.object_id = object_id(’YourTable’)
and spart.index_id < 2

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

Если вы используете SQL 2000, вы можете использовать таблицу sysindexes для получения номера.

select max(ROWS)
from sysindexes
where id = object_id(’YourTable’)

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

Ответ 2

попробуйте это, если вы хотите знать количество строк:

exec sp_spaceused [TABLE_NAME]

Ответ 3

Если вы посмотрите планы выполнения своих запросов, вы увидите, что происходит.

Ваш первый запрос if (select count(*) from BookChapters) = 0 распознается оптимизатором запросов так же, как if exists(select * from BookChapters). SQL Server знает, что выражение истинно, если присутствует хотя бы одна строка, поэтому он ищет наличие одной строки, а не подсчет всех строк в таблице.

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

Ответ 4

Вы рассматривали запрос select count(BookChapterId) from BookChapterTable? - где `BookChapterId является некластеризованным индексом. Это должно ускорить работу.

В зависимости от того, как используется таблица и доступ к строкам, ключевым моментом может быть запрос к некластеризованному индексу: я просто взял несколько баллов из MDSN:

  • Прежде чем создавать некластеризованные индексы, поймите, как ваши данные будут доступ к ним. Рассмотрите возможность использования некластеризованных индексов для:
  • Столбцы, содержащие большое количество различных значений, например, комбинация имени и имени (если используется кластеризованный индекс для других столбцов). Если существует очень мало различных значений, например, только 1 и 0, большинство запросов не будут использовать индекс, потому что таблица сканирование обычно более эффективно.
  • Запросы, которые не возвращают большие результирующие наборы.
  • Столбцы, часто участвующие в условиях поиска запроса (WHERE) ), которые возвращают точные соответствия.
  • Приложения системы поддержки принятия решений, для которых объединяются и группируются часто требуется. Создание нескольких некластеризованных индексов в столбцах участвуют в операции объединения и группирования, а кластерный индекс - любые столбцы внешнего ключа.
  • Покрытие всех столбцов из одной таблицы в заданном запросе. Это устраняет доступ к таблице или кластерному индексу в целом.

Ответ 5

попробуйте это, если вам нужно обнаружить, если в таблице больше строк, чем одна:

if (SELECT COUNT(*) FROM (SELECT TOP 2 * FROM BookChapters) AS b) > 1