количество строк в большой таблице

#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 Server COUNT(PK) , COUNT(*) COUNT(1) , COUNT(any NON NULL column) COUNT(*) все преобразуется в, ,, в ,, в ,, в, в плане выполнения. Между ними нет разницы.

3. Единственное различие здесь заключается в том, нужно ли SQL server сначала запрашивать схему перед подсчетом кортежей, что может быть в случае с COUNT(*). Это не повлияет на количество строк, но может повлиять на скорость выполнения. В данном случае это зависит от версии SQL server.