#sql #sql-server #tsql
#sql #sql-сервер #tsql
Вопрос:
SELECT COUNT(*) FROM BigTable_1
Какой способ я должен использовать, чтобы получить количество строк в таблице, если у меня более 1 миллиарда строк?
ОБНОВЛЕНИЕ: Например, если у нас «проблема с таймаутом» в приведенном выше запросе, есть ли какой-либо способ его оптимизировать? Как сделать это быстрее?
Комментарии:
1. Вы ответили на свой собственный вопрос… @_@
2. Вы спрашиваете об этом, потому что
COUNT(*)
это слишком медленно, и вы ищете более быструю альтернативу? Вы действительно должны указать это.
Ответ №1:
Если вам нужно точное количество, вы должны использовать COUNT (*)
Если вас устраивает приблизительный подсчет, вы можете использовать сумму строк в разделах
SELECT SUM (Rows)
FROM sys.partitions
WHERE 1=1
And index_id IN (0, 1)
And OBJECT_ID = OBJECT_ID('Database.schema.Table');
Если вы хотите быть смешным со своим COUNT
, вы можете сделать следующее
select COUNT (1/0) from BigTable_1
Комментарии:
1. Что означает «сумма строк в разделе (разделах)»?
2. @pst если таблица разбита на разделы, она получит количество строк для всех разделов.
3. @Ben Thul — Пока у вас есть необходимые разрешения для таблицы / столбцов, оптимизатор SQL Server игнорирует все, что находится внутри круглой скобки в
COUNT ()
Ответ №2:
Очень быстрая ОЦЕНКА:
выберите count(*) из таблицы
Но не выполняйте! Выделите код, нажмите ctl-l, чтобы открыть план запроса. Затем наведите указатель мыши на крайнюю левую стрелку. Появится желтое поле с предполагаемым количеством строк.
Вы можете запрашивать системные таблицы, чтобы получить те же данные, но это сложнее запомнить. Этот способ гораздо более впечатляет зрителей.
🙂
Комментарии:
1. 1 За то, что ты умный / непохожий. Но я верю, что сбитая с толку статистика может сбить с толку этот путь 😉
Ответ №3:
Вы можете использовать sys.dm_db_partition_stats.
select sum(row_count)
from sys.dm_db_partition_stats
where object_id = object_id('TableName') and index_id < 2
Ответ №4:
В зависимости от ваших требований к параллелизму, скорости и точности, вы можете получить приблизительный ответ с помощью триггеров. Создайте таблицу
CREATE TABLE TABLE_COUNTS(TABLE_NAME VARCHAR, R_COUNT BIGINT DEFAULT 0);
INSERT INTO TABLE_COUNTS('BigTable_1', 0);
(Я собираюсь опустить добавление ключа и т.д., для краткости.)
Теперь настройте триггеры.
CREATE TRIGGER bt1count_1 AFTER INSERT ON BigTable_1 FOR EACH ROW
BEGIN
UPDATE TABLE_COUNTS SET R_COUNT=R_COUNT 1 WHERE TABLE_NAME='BigTable_1';
END;
Соответствующий триггер уменьшения запускается при удалении. Теперь вместо COUNT вы запрашиваете таблицу TABLE_COUNT. Ваш результат будет немного отличаться в случае ожидающих транзакций, но вы можете смириться с этим. И стоимость амортизируется за все операции ВСТАВКИ и УДАЛЕНИЯ; получение количества строк, когда вам это нужно, происходит быстро.
Ответ №5:
Попробуйте это:
select sum(P.rows) from sys.partitions P with (nolock)
join sys.tables T with (nolock) on P.object_id = T.object_id
where T.Name = 'Table_1' and index_id = 1
это должно быть намного быстрее. Понял это отсюда: ВЫБЕРИТЕ COUNT (*) ДЛЯ БОЛЬШОЙ ТАБЛИЦЫ
Комментарии:
1. Имеет ли это / подразумевает / налагает какую-либо точность? (Предполагая для простоты отсутствие параллельных транзакций.)
2. @pst: столбец rows не обновляется в режиме реального времени в sys.partitions; это будет лишь приблизительная оценка. Но для таблицы с 1G строками это похоже на старую шутку: температура солнца составляет несколько миллионов градусов по Цельсию или градусов по Фаренгейту? Ответ: имеет ли это значение?
3. @Ben — Он обновляется практически в режиме реального времени на основе тестов, которые я проводил в прошлом. Действительно, одна из критических замечаний к нему может заключаться в том, что он имеет эффект незафиксированных транзакций, он также учитывает указатели пересылки в куче и может быть изменен вручную
4. Все, что я говорю, это то, что BOL говорит об этом столбце: «Приблизительное количество строк в этом разделе». Примите это за то, чего это стоит.
5. @Ben — Действительно. В моем комментарии были указаны 3 другие причины, по которым это может быть неточно!
Ответ №6:
Ваш запрос получит количество строк независимо от количества. Попробуйте использовать запрос, который вы указали в своем вопросе.
Комментарии:
1. На самом деле, если у них намного больше 2 миллиардов строк, им нужно будет использовать
COUNT_BIG
вместо этого.
Ответ №7:
Существует только 1 [точный] способ подсчета строк в таблице: count(*)
. sp_spaceused
или просмотр статистики не обязательно даст вам правильный ответ [a?].
Ответ №8:
если у вас есть первичный ключ, вы должны быть в состоянии сделать это:
выберите count (PrimaryKey) из table_1
Комментарии:
1. Я не собираюсь голосовать против, но столбец, предоставленный в
COUNT(...)
, не должен иметь отношения к оптимизатору запросов — например,COUNT(*)
не нужно выполнять больше работы, чемCOUNT(x)
поскольку сами кортежи (независимо от содержащихся в них столбцов) в результирующем наборе учитываются.2. @pst — Верно только для
NON NULL
столбцов, конечно. В SQL ServerCOUNT(PK)
,COUNT(*)
COUNT(1)
,COUNT(any NON NULL column)
COUNT(*)
все преобразуется в, ,, в ,, в ,, в, в плане выполнения. Между ними нет разницы.3. Единственное различие здесь заключается в том, нужно ли SQL server сначала запрашивать схему перед подсчетом кортежей, что может быть в случае с COUNT(*). Это не повлияет на количество строк, но может повлиять на скорость выполнения. В данном случае это зависит от версии SQL server.