Самый быстрый способ подсчета точного количества строк в очень большой таблице?

234

Я сталкивался со статьями, в которых говорится, что SELECT COUNT(*) FROM TABLE_NAMEбудет медленно, когда в таблице много строк и много столбцов.

У меня есть таблица, которая может содержать даже миллиарды строк (в ней примерно 15 столбцов). Есть ли лучший способ получить точный счетчик количества строк в таблице?

Пожалуйста, рассмотрите следующее перед вашим ответом:

  • Я ищу независимое решение от поставщика базы данных. Это нормально, если он охватывает MySQL , Oracle , MS SQL Server . Но если на самом деле не существует независимого от поставщика баз данных решения, я остановлюсь на разных решениях для разных поставщиков баз данных.

  • Я не могу использовать любой другой внешний инструмент для этого. Я в основном ищу решение на основе SQL.

  • Я не могу больше нормализовать дизайн моей базы данных. Он уже в 3NF, и, кроме того, много кода уже написано вокруг него.

Сваранга Сарма
источник
4
И просто любопытно, зачем нужно точное мгновенное количество строк, когда у вас их миллиарды ...
zerkms
2
Разве мы все не надеемся, что эта конкретная конструкция была оптимизирована нашим поставщиком баз данных?
KevinDTimm
5
@Swaranga, не могли бы вы рассказать немного больше о том, какова цель обслуживания базы данных, которая должна знать точное количество строк в таблице? Я не могу представить. И, как говорит Кевин, если бы был более быстрый способ, чем COUNT (*), то поставщик СУБД (должен) наверняка повторно внедрил бы COUNT (*), чтобы использовать его ...
Тони Эндрюс
3
Конечно, если таблица часто записывается, то ваш точный счет будет точным только для определенного момента времени, и может даже не быть точным, если другие процессы записывают в таблицу, если вы не установили блокировку таблицы для запроса.
Стив Форд
2
Вы могли бы использовать триггеры вставки и удаления, чтобы вести скользящий счет?
Папараццо

Ответы:

246

Простой ответ:

  • Независимое решение от поставщика базы данных = использовать стандарт = COUNT(*)
  • Существуют приблизительные решения SQL Server, но не используйте COUNT (*) = вне области

Ноты:

COUNT (1) = COUNT (*) = COUNT (PrimaryKey) на всякий случай

Редактировать:

Пример SQL Server (1,4 миллиарда строк, 12 столбцов)

SELECT COUNT(*) FROM MyBigtable WITH (NOLOCK)
-- NOLOCK here is for me only to let me test for this answer: no more, no less

1 пробег, 5:46 минут, счет = 1 401 659 700

--Note, sp_spaceused uses this DMV
SELECT
   Total_Rows= SUM(st.row_count)
FROM
   sys.dm_db_partition_stats st
WHERE
    object_name(object_id) = 'MyBigtable' AND (index_id < 2)

2 прогона, оба менее 1 секунды, количество = 1 401 659 670

Второй имеет меньше строк = неправильно. Будет одинаковым или более в зависимости от записи (удаление выполняется в нерабочее время)

ГБН
источник
9
Нет COUNT(*) = COUNT(key). Это просто неправильно. Если нет NOT NULLограничений - тогда они могут быть не равны (как в результатах, так и в плане выполнения).
zerkms
14
@zerkmsby: для COUNT (ключ) я имел в виду COUNT (primarykey), который не должен обнуляться. Я
уточню
8
с (NOLOCK) это не то, что позволяет ему работать на производстве, и это может привести к неточному подсчету. Когда вы используете эту подсказку, убедитесь, что она предотвращает блокировки, но побочные эффекты от производственной коробки заключаются в том, что вы можете считать строки дважды в некоторых ситуациях или пропускать строки в других ситуациях. NOLOCK лучше использовать для таблицы, в которую не производится запись, поскольку она допускает «грязное чтение». Не советуйте людям использовать эту подсказку, если они не полностью понимают последствия
Давос
4
@mishrsud Единственный точный запрос - SELECT COUNT (*), но он медленный. Вы можете иметь точный и медленный или грубый и быстрый. То, что вы будете делать, будет зависеть от того, что важнее для цели, для которой вам нужен счет. NO LOCK может включать или даже исключать строки, которые являются промежуточными или движущимися страницами по любой причине.
Давос,
5
@gbn очень хорошее решение, можете ли вы сказать, что такое использование index_id < 2?
совершить
29

Самый быстрый способ на MySQL - это:

SHOW TABLE STATUS;

Вы сразу получите все свои таблицы с количеством строк (которое является общим) вместе с большим количеством дополнительной информации, если хотите.

salbahra
источник
1
Умный способ .. с этим вы можете получить количество строк нескольких таблиц в 1 запросе.
Деваль Хандельвал
Вы работали на БД с таблицами с ~ миллиардами записей типа @gbn и заметили время?
KNU
какое значение составляет общее количество строк для всех таблиц в базе данных? И это приблизительные - что если вы хотите точные значения количества строк?
Kreeverp
2
это вообще не работает, например, в INNODB механизм хранения считывает несколько строк и экстраполирует, чтобы угадать количество строк
Мартин Шеффер
10

Я сталкивался со статьями, в которых говорится, что SELECT COUNT (*) FROM TABLE_NAME будет медленным, когда в таблице много строк и много столбцов.

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

Обратите внимание, что в целом вы можете извлечь хорошую оценку, используя инструменты оптимизации запросов, статистику таблиц и т. Д. Например, в случае с PostgreSQL вы можете проанализировать выходные данные explain count(*) from yourtableи получить достаточно хорошую оценку числа строк. Что подводит меня к вашему второму вопросу.

У меня есть таблица, которая может содержать даже миллиарды строк (в ней примерно 15 столбцов). Есть ли лучший способ получить точный счетчик количества строк в таблице?

Шутки в сторону? :-) Вы действительно имеете в виду точное количество таблиц с миллиардами строк? Вы действительно уверены? :-)

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

Дени де Бернарди
источник
Да, Денис, точный счет не требуется. :(
Сваранга Сарма
5
К счастью, менеджеры Google более разумны, чем ваш начальник ... Представьте, насколько медленным было бы возвращение точного числа результатов поиска по каждому из ваших запросов вместо того, чтобы придерживаться оценочного числа.
Дени де Бернарди
По крайней мере, вы сопереживаете мне. Как насчет единственного решения Oracle? Это уменьшит мою проблему до некоторой степени. В настоящее время клиент использует Oracle; так что, если я придумаю обходной путь только для Oracle, это подойдет [на данный момент]. :)
Сваранга Сарма
6
«Да, Денис, точное количество требуется. :(» - ну, я могу только догадываться. Обнаружит ли процесс обслуживания БД 42423,876 строк в таблице A, а затем создает 42,123,876 пустых строк в таблице B, а затем перебирает таблицу А и обновить строки в таблице Б ...? Или это безумнее, чем это? ;-)
Тони Эндрюс
1
Транзакция 2 не может начаться до совершения транзакции 1. Без обновления «таблицы счетов» многие транзакции обновления могут выполняться параллельно. С помощью «таблицы счетов» каждая транзакция должна «получить билет» для обновления своего счета. Таким образом, транзакции начинают стоять в очереди в билетном автомате (планировщик решает, кто будет следующим, кто получит блокировку таблицы подсчетов).
Эрвин Смут
10

Есть ли лучший способ получить точный счетчик количества строк в таблице?

Чтобы ответить на ваш вопрос просто, нет .

Если вам нужен независимый от СУБД способ сделать это, самый быстрый способ всегда будет:

SELECT COUNT(*) FROM TableName

У некоторых поставщиков СУБД могут быть более быстрые способы, которые будут работать только для их систем. Некоторые из этих вариантов уже опубликованы в других ответах.

COUNT(*) в любом случае должна быть оптимизирована СУБД (по крайней мере, любой достойной БД PROD), поэтому не пытайтесь обойти их оптимизацию.

С другой стороны:
я уверен, что выполнение многих других ваших запросов также занимает много времени из-за размера таблицы. Любые проблемы с производительностью, вероятно, следует решать, думая о дизайне схемы с учетом скорости. Я понимаю, что вы сказали, что это не вариант изменить, но может оказаться, что более 10 минутных запросов тоже не вариант. 3-я NF не всегда лучший подход, когда вам нужна скорость, и иногда данные могут быть разделены на несколько таблиц, если записи не должны храниться вместе. Что-то думать о...

Джесси Уэбб
источник
10

Я получил этот скрипт из другого вопроса / ответа StackOverflow:

SELECT SUM(p.rows) FROM sys.partitions AS p
  INNER JOIN sys.tables AS t
  ON p.[object_id] = t.[object_id]
  INNER JOIN sys.schemas AS s
  ON s.[schema_id] = t.[schema_id]
  WHERE t.name = N'YourTableNameHere'
  AND s.name = N'dbo'
  AND p.index_id IN (0,1);

В моей таблице 500 миллионов записей, а результат выше чем за 1 мс. В то же время,

SELECT COUNT(id) FROM MyTable

занимает целых 39 минут 52 секунды!

Они дают одинаковое количество строк (в моем случае, точно 519326012).

Я не знаю, будет ли это всегда так.

JakeJ
источник
Можете ли вы добавить параметр, чтобы получить количество строк с этим запросом? Пример: выберите COUNT (1) FROM TABLENAME WHERE ColumnFiled = '1' С вашим запросом?
VnDevil
То есть количество - количество строк (записей) в данном случае является «количеством». «500 миллионов записей» - это приблизительное число, а «519326012» - точное количество строк или число. Строки = записи = количество.
ДжейкJ
9

Вы можете попробовать это sp_spaceused (Transact-SQL)

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

джемы
источник
Не даст ли sp_spaceused приблизительный подсчет?
Сваранга Сарма
1
К вашему сведению: это использует sys.dm_db_partition_stats для внутреннего использования
gbn
6

Если выпуск SQL Server 2005/2008, вы можете использовать DMV для вычисления количества строк в таблице:

-- Shows all user tables and row counts for the current database 
-- Remove is_ms_shipped = 0 check to include system objects 
-- i.index_id < 2 indicates clustered index (1) or hash table (0) 
SELECT o.name, 
 ddps.row_count 
FROM sys.indexes AS i 
 INNER JOIN sys.objects AS o ON i.OBJECT_ID = o.OBJECT_ID 
 INNER JOIN sys.dm_db_partition_stats AS ddps ON i.OBJECT_ID = ddps.OBJECT_ID 
 AND i.index_id = ddps.index_id 
WHERE i.index_id < 2 
 AND o.is_ms_shipped = 0 
ORDER BY o.NAME 

Для ядра базы данных SQL Server 2000 будут работать sysindexes, но настоятельно рекомендуется избегать его использования в будущих выпусках SQL Server, поскольку он может быть удален в ближайшем будущем.

Пример кода взят из: Как быстро и безболезненно получить счетчик строк таблицы

Алиреза Мадда
источник
Это приблизительный, а не точный : смотрите мой ответ, пожалуйста
gbn
Вы знаете пример, где это не точно? AFAIK, это не зависит от обновленной статистики.
Алиреза Мадда
5

я использую

select /*+ parallel(a) */  count(1) from table_name a;
Майнш С
источник
выберите / * + параллель (a) * / count (1) из таблицы_имя a
Mainsh S
5

Я не настолько эксперт, как другие, кто ответил, но у меня возникла проблема с процедурой, которую я использовал для выбора случайной строки из таблицы (не слишком релевантно), но мне нужно было знать количество строк в моей справочной таблице. рассчитать случайный индекс. Используя традиционную работу Count (*) или Count (1), но я иногда получал до 2 секунд для выполнения моего запроса. Поэтому вместо этого (для моей таблицы с именем 'tbl_HighOrder') я использую:

Declare @max int

Select @max = Row_Count
From sys.dm_db_partition_stats
Where Object_Name(Object_Id) = 'tbl_HighOrder'

Он отлично работает и время запросов в Management Studio равно нулю.

Джон Рейнс
источник
1
FWIW, вы должны указать, какого поставщика базы данных вы используете; Я думаю, что заявление будет немного отличаться в зависимости от поставщика.
ToolmakerSteve
5

Ну, опоздал на 5 лет и не уверен, поможет ли это

Я пытался посчитать нет. строк в таблице SQL Server с использованием MS SQL Server Management Studio и столкнулся с некоторой ошибкой переполнения, тогда я использовал следующее:

выберите count_big (1) FROM [имя_БД]. [dbo]. [FactSampleValue];

Результат :

24296650578 строк

Калиюг Антагонист
источник
5

Я нашел эту хорошую статью SQL Server - HOW-TO: быстро получить точное количество строк для таблицы изmartijnh1 которой можно получить хорошее резюме для каждого сценария.

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

А пока вот подробности из статьи:

Способ 1:

Запрос:

SELECT COUNT(*) FROM Transactions 

Комментарии:

Выполняет полное сканирование таблицы. Медленно на больших столах.

Способ 2:

Запрос:

SELECT CONVERT(bigint, rows) 
FROM sysindexes 
WHERE id = OBJECT_ID('Transactions') 
AND indid < 2 

Комментарии:

Быстрый способ получить количество строк. Зависит от статистики и неточно.

Запустите DBCC UPDATEUSAGE (База данных) с COUNT_ROWS, что может занять значительное время для больших таблиц.

Способ 3:

Запрос:

SELECT CAST(p.rows AS float) 
FROM sys.tables AS tbl 
INNER JOIN sys.indexes AS idx ON idx.object_id = tbl.object_id and
idx.index_id < 2 
INNER JOIN sys.partitions AS p ON p.object_id=CAST(tbl.object_id AS int) 
AND p.index_id=idx.index_id 
WHERE ((tbl.name=N'Transactions' 
AND SCHEMA_NAME(tbl.schema_id)='dbo')) 

Комментарии:

Способ, которым студия управления SQL подсчитывает строки (посмотрите на свойства таблицы, хранилище, количество строк). Очень быстро, но все же приблизительное количество строк.

Способ 4:

Запрос:

SELECT SUM (row_count) 
FROM sys.dm_db_partition_stats 
WHERE object_id=OBJECT_ID('Transactions')    
AND (index_id=0 or index_id=1); 

Комментарии:

Быстрая (хотя и не такая быстрая, как метод 2) операция и, что не менее важно, надежная.

Thierry
источник
Спасибо! Действительно полезный совет. У меня нет разрешения на просмотр системных таблиц, поэтому метод 4 - это не я. Однако метод 3 достаточно хорош.
Николас Хамфри
3

Я не думаю, что есть общее всегда быстрое решение: некоторые СУБД / версии имеют специальную оптимизацию, для SELECT COUNT(*)которой используются более быстрые опции, в то время как другие просто сканируют таблицы. Вам нужно будет перейти на сайты документации / поддержки для второго набора, который, вероятно, потребует написания более конкретного запроса, обычно такого, который каким-то образом попадает в индекс.

РЕДАКТИРОВАТЬ:

Вот мысль, которая может сработать, в зависимости от вашей схемы и распределения данных: есть ли у вас индексированный столбец, который ссылается на возрастающее значение, числовой возрастающий идентификатор, скажем, или даже на временную метку или дату? Затем, при условии, что удаления не произойдет, должна быть возможность сохранить счетчик до некоторого недавнего значения (вчерашняя дата, наибольшее значение идентификатора в некоторой недавней точке выборки) и добавить счетчик сверх этого, который должен очень быстро разрешиться в индексе. , Конечно, очень сильно зависит от значений и индексов, но применимо практически ко всем версиям любой СУБД.

Майк Вудхаус
источник
Я бы очень надеялся, что любая приличная СУБД будет использовать индекс для SELECT COUNT(*). Даже MySQL, очевидно, делает это ...
слеське
при условии, что удаление не произойдет - серьезно? ; p
ToolmakerSteve
3

Я опоздал на этот вопрос, но вот что вы можете сделать с MySQL (поскольку я использую MySQL). Я делюсь своими наблюдениями здесь:

1) SELECT COUNT(*) AS TOTAL_ROWS FROM <TABLE_NAME>

Результат Количество строк
: 508534 Вывод на
консоль: Затронутые строки: 0 Найдено строк: 1 Предупреждения: 0 Продолжительность 1 запроса: 0,125 сек.
Требуется время для таблицы с большим количеством строк, но количество строк очень точное.

2) SHOW TABLE STATUS or SHOW TABLE STATUS WHERE NAME="<TABLE_NAME>"

Результат
Количество строк : 511235 Вывод на
консоль: Затронутые строки: 0 Найдено строк: 1 Предупреждения: 0 Продолжительность 1 запроса: 0,250 сек. Резюме: Количество строк не является точным.

3) SELECT * FROM information_schema.tables WHERE table_schema = DATABASE();

Результат
Количество строк : 507806 Вывод на
консоль: Затронутых строк: 0 Найдено строк: 48 Предупреждений: 0 Продолжительность 1 запроса: 1,701 сек.
Количество строк не является точным.

Я не MySQL или эксперт по базам данных, но я обнаружил, что для очень больших таблиц вы можете использовать вариант 2 или 3 и получить «точное представление» о количестве присутствующих строк.

Мне нужно было получить количество строк для отображения некоторых статистических данных в пользовательском интерфейсе. С помощью вышеупомянутых запросов я знал, что общее количество строк было более 500 000, поэтому я придумал показывать статистику типа «Более 500 000 строк» ​​без точного количества строк.

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

sunitkatkar
источник
2

Не совсем независимое от СУБД решение, но, по крайней мере, ваш клиентский код не увидит разницы ...

Создайте другую таблицу T с одной строкой и одним целочисленным полем N 1 и создайте INSERT TRIGGER, который просто выполняет:

UPDATE T SET N = N + 1

Также создайте DELETE TRIGGER, который выполняет:

UPDATE T SET N = N - 1

СУБД, достойная своей соли, будет гарантировать атомарность операций выше 2 , а N будет всегда содержать точное количество строк, которое потом будет очень быстро получить:

SELECT N FROM T

Хотя триггеры зависят от СУБД, выбор из T не обязателен, и ваш клиентский код не нужно будет менять для каждой поддерживаемой СУБД.

Тем не менее, это может иметь некоторые проблемы с масштабируемостью, если таблица является INSERT или DELETE-интенсивной, особенно если вы не делаете COMMIT сразу после INSERT / DELETE.


1 Эти имена просто заполнители - используйте что-то более значимое в производстве.

2 Т.е. N не может быть изменено одновременной транзакцией между чтением и записью в N, если и чтение, и запись выполняются в одном операторе SQL.

Бранко Димитриевич
источник
2

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

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

-- First slave
SELECT COUNT(pk) FROM t WHERE pk < 250000000
-- Ith slave where 2 <= I <= N - 1
SELECT COUNT(pk) FROM t WHERE pk >= I*250000000 and pk < (I+1)*250000000
-- Last slave
SELECT COUNT(pk) FROM t WHERE pk > (N-1)*250000000

Но вам нужен только SQL. Что за бюст. Хорошо, так скажем, вы садомазохист. На главном (или ближайшем подчиненном) вам, скорее всего, нужно создать таблицу для этого:

CREATE TABLE counter_table (minpk integer, maxpk integer, cnt integer, slaveid integer)

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

INSERT INTO counter_table VALUES (I*25000000, (I+1)*250000000, (SELECT COUNT(pk) FROM ... ), @@SLAVE_ID)

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

-- A table per slave!
INSERT INTO counter_table_slave_I VALUES (...)

В конце концов у вас должен быть ведомый, который существует последним на пути, пройденном графом репликации, относительно первого ведомого. Это ведомое устройство должно теперь иметь все другие значения счетчика и иметь свои собственные значения. Но к тому времени, как вы закончите, вероятно, будут добавлены строки, так что вам нужно будет вставить еще одну, компенсирующую записанный max pk в вашей counter_table и текущий max pk.

На этом этапе вам нужно было бы выполнить агрегатную функцию, чтобы выяснить, каково общее количество строк, но это проще, так как вы будете запускать его не более чем на «число ведомых устройств, которые вы имеете и меняете».

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

SELECT SUM(cnt) FROM (
    SELECT * FROM counter_table_slave_1
      UNION
    SELECT * FROM counter_table_slave_2
      UNION
    ...
  )

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

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

Но если у вас хорошая репликация, то ваш прирост скорости должен быть напрямую связан с числом или рабами. Фактически, если для выполнения одного запроса подсчета требуется 10 минут, а у вас есть 8 подчиненных, вы бы сократили свое время до пары минут. Может быть, час, чтобы сгладить детали этого решения.

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

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

Так вот мои две копейки 2013 года.

Янгмун Чой
источник
2

Если триггер вставки слишком дорогой в использовании, но триггер удаления может быть предоставлен, и имеется автоматическое увеличениеid , то после однократного подсчета всей таблицы и запоминания счетчика как last-countиlast-counted-id ,

затем каждый день просто нужно рассчитывать на id> last-counted-id, добавить это last-countи сохранить новыйlast-counted-id .

Триггер удаления уменьшит число последних записей, если идентификатор удаленной записи <= идентификатор последней записи.

ToolmakerSteve
источник
.. извините, у меня нет времени, чтобы показать SQL, который будет использоваться (мой SQL ржавый). Если кто-то захочет отредактировать мой ответ и добавить SQL, это было бы здорово!
ToolmakerSteve
1

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

SELECT TOP(1) <primarykeyfield> FROM <table> ORDER BY <primarykeyfield> DESC;

Я работаю с таблицами MS SQL, содержащими миллиарды строк, для которых требуется время отклика не более секунды для данных, включая количество записей. Подобный SELECT COUNT (*) может занять несколько минут для сравнения.

Kevins
источник
1
Не совсем верно - что если INSERTоткат транзакции? Это значение первичного ключа будет отсутствовать, поэтому фактическое количество записей будет на единицу меньше максимального значения.
Сэр Криспалот
Могут быть пробелы в последовательности. Обычно это результат откатов.
Osa E
На самом деле, есть модификация этого ответа, которая может быть значительно быстрее, чем count(*), если поставщик базы данных недостаточно оптимизирован count(*): каждый день отслеживайте последний автоиндекс и соответствующий ему счетчик, а затем запрашивайте количество записей за ним. Может также обрабатывать deletes, если добавить при удалении триггер, который уменьшает предыдущий итог, если идентификатор удаленной записи <= этот последний автоиндекс.
ToolmakerSteve
1

Для сервера Sql попробуйте это

SELECT T.name, 
       I.rows AS [ROWCOUNT] 
FROM   sys.tables AS T 
       INNER JOIN sys.sysindexes AS I 
               ON T.object_id = I.id AND I.indid < 2 
WHERE T.name = 'Your_Table_Name'
ORDER  BY I.rows DESC 
Абхишек Б Патель
источник
0

выберите строки из sysindexes, где id = Object_ID ('TableName') и indid <2

Enzero
источник
0

Поместите индекс в какой-то столбец. Это должно позволить оптимизатору выполнить полное сканирование блоков индекса, а не полное сканирование таблицы. Это сократит ваши затраты на ввод-вывод. Посмотрите на план выполнения до и после. Затем измерьте время настенных часов в обоих направлениях.

EvilTeach
источник
Если в таблице есть миллиарды строк без индекса для какого-либо столбца, тогда будут широко распространенные проблемы с производительностью, выходящие далеко за рамки потребности, выраженной в исходном вопросе ... но хорошо, что вы упомянули это (не предполагайте ничего!) :)
ToolmakerSteve
0

Если вы используете Oracle, как насчет этого (при условии, что статистика таблицы обновлена):

select <TABLE_NAME>, num_rows, last_analyzed from user_tables

last_analyzed покажет время последней статистики.

Диого Феррейра
источник
0

С PostgreSQL:

SELECT reltuples AS approximate_row_count FROM pg_class WHERE relname = 'table_name'
Дориан
источник
-1

В SQL Server 2016 я могу просто проверить свойства таблицы и затем выбрать вкладку «Хранилище» - это дает мне количество строк, дисковое пространство, используемое таблицей, индексное пространство и т. Д.

сенсей
источник
Он искал database vendor independent solution. Также это требует графического интерфейса и не может быть автоматизирован. Также это не быстрее, чем COUNT (*)
Фридер
-3

Может быть немного поздно, но это может помочь другим для MSSQL

; С RecordCount AS (ВЫБРАТЬ ROW_NUMBER () ПЕРЕВЕРНУТЬСЯ (ЗАКАЗАТЬ ПО COLUMN_NAME) AS [RowNumber] FROM TABLE_NAME) ВЫБРАТЬ МАКС (RowNumber) FROM RecordCount

Юстус Свейнвелдер
источник
Это значительно медленнее, чем COUNT (), если только нам ОЧЕНЬ не повезло и оптимизатору не удалось оптимизировать его до COUNT () - зачем спрашивать SORT по случайному столбцу?!?
dsz