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

Количество серверов SQL медленное

Подсчет таблиц с большим объемом данных может быть очень медленным, иногда требуется минут; он также может создавать тупик на занятом сервере. Я хочу отображать реальные значения, NOLOCK не является вариантом.

Серверы, которые я использую, - это SQL Server 2005 или 2008 Standard или Enterprise - если это имеет значение. Я могу представить, что SQL Server поддерживает подсчеты для каждой таблицы, и если нет предложения WHERE, я мог бы получить этот номер довольно быстро, правильно?

Например:

SELECT COUNT(*) FROM myTable

должен немедленно вернуться с правильным значением. Нужно ли полагаться на статистику, которую нужно обновить?

4b9b3361

Ответ 1

Очень близким приблизительным (игнорируя любые транзакции в полете) будет:

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'myTable'
  AND s.name = N'dbo'
  AND p.index_id IN (0,1);

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

Если у вас есть некоторое подмножество таблицы, которую вы хотите сосчитать (скажем, WHERE some_column IS NULL), вы можете создать отфильтрованный индекс для этого столбца и структурировать предложение where тем или иным образом, в зависимости от того, было ли это исключением или правило (поэтому создайте отфильтрованный индекс на меньшем наборе). Итак, один из этих двух индексов:

CREATE INDEX IAmTheException ON dbo.table(some_column)
  WHERE some_column IS NULL;

CREATE INDEX IAmTheRule ON dbo.table(some_column)
  WHERE some_column IS NOT NULL;

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

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]
  INNER JOIN sys.indexes AS i
  ON p.index_id = i.index_id
  WHERE t.name = N'myTable'
  AND s.name = N'dbo'
  AND i.name = N'IAmTheException' -- or N'IAmTheRule'
  AND p.index_id IN (0,1);

И если вы хотите знать обратное, просто вычтите из первого запроса выше.

Ответ 2

(Насколько велико "большой объем данных"? - должен был прокомментировать это в первую очередь, но, возможно, ниже приведен пример exec)

Если я запускаю запрос на статике (означает, что никто больше не раздражает чтение/запись/обновления в течение довольно длительного времени, так что конфликт не является проблемой) таблица с 200 миллионами строк и COUNT (*) через 15 секунд на моем dev (оракул). Учитывая чистый объем данных, это все еще довольно быстро (по крайней мере для меня)

Как вы сказали, NOLOCK не является вариантом, вы можете рассмотреть

exec sp_spaceused 'myTable'

.

Но это приближается почти так же, как NOLOCK (игнорируя contention + delete/update afaik)

Ответ 3

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

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

select 
    row_count
from sys.dm_db_partition_stats as p
inner join sys.indexes as i 
  on p.index_id = i.index_id
  and p.object_id = i.object_id
where   i.name = 'your index'

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

Как сказал Аарон Бертран, сохранение запроса может быть более дорогостоящим, чем использование уже существующего. Таким образом, выбор за вами.

Ответ 4

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

  1. Выберите папку "Таблицы" в дереве базы данных (Object Explorer)
  2. Нажмите клавишу F7 или выберите " Вид" > " Сведения о проводнике объектов", чтобы открыть представление " Сведения о проводнике объектов".
  3. В этом представлении вы можете щелкнуть правой кнопкой мыши заголовок столбца, чтобы выбрать столбцы, которые вы хотите увидеть, включая используемое табличное пространство, используемое индексное пространство и количество строк: enter image description here

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

Ответ 5

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

MySQL> connect information_schema;
MySQL> select table_name,table_rows from tables;