Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

A contagem do SQL Server está lenta


Aproximado muito próximo (ignorando quaisquer transações em voo) seria:
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);

Isso retornará muito, muito mais rápido que COUNT(*) , e se sua tabela está mudando rápido o suficiente, não é realmente menos precisa - se sua tabela mudou entre quando você iniciou sua COUNT (e bloqueios foram obtidos) e quando ela foi retornada (quando os bloqueios foram liberados e todas as transações de gravação em espera agora foram autorizados a escrever na mesa), é muito mais valioso? Eu não acho.

Se você tiver algum subconjunto da tabela que deseja contar (digamos, WHERE some_column IS NULL ), você pode criar um índice filtrado nessa coluna e estruturar a cláusula where de uma forma ou de outra, dependendo se foi a exceção ou a regra (portanto, crie o índice filtrado no conjunto menor). Então, um desses dois índices:
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;

Então você pode obter a contagem de maneira semelhante usando:
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);

E se você quiser saber o contrário, basta subtrair da primeira consulta acima.