A maneira mais rápida de contar o número exato de linhas em uma tabela muito grande?


234

Encontrei artigos que afirmam que SELECT COUNT(*) FROM TABLE_NAMEserão lentos quando a tabela tiver muitas linhas e muitas colunas.

Eu tenho uma tabela que pode conter até bilhões de linhas [tem aproximadamente 15 colunas]. Existe uma maneira melhor de obter a contagem EXATA do número de linhas de uma tabela?

Considere o seguinte antes da sua resposta:

  • Estou procurando uma solução independente de fornecedor de banco de dados. Tudo bem se ele cobre MySQL , Oracle , MS SQL Server . Mas se realmente não houver uma solução independente de fornecedor de banco de dados, decidirei por soluções diferentes para diferentes fornecedores de banco de dados.

  • Não posso usar nenhuma outra ferramenta externa para fazer isso. Estou procurando principalmente uma solução baseada em SQL.

  • Não posso normalizar mais o design do meu banco de dados. Já está no 3NF e, além disso, muitos códigos já foram escritos em torno dele.


4
E apenas curioso porque ele é necessário a quantidade instante exato de linhas quando você tem bilhões deles ...
zerkms

2
Todos nós não esperamos que essa construção em particular tenha sido otimizada por nosso fornecedor de banco de dados?
KevinDTimm

5
@Swaranga, você pode esclarecer um pouco mais sobre qual é a finalidade dessa manutenção de banco de dados que deve saber o número exato de linhas na tabela? Não consigo imaginar. E como diz Kevin, se houvesse uma maneira mais rápida do que COUNT (*), em seguida, o fornecedor DBMS que (deve) certamente reimplementar COUNT (*) para usá-lo ...
Tony Andrews

3
Certamente, se a tabela estiver sendo gravada com frequência, sua contagem exata será exata apenas para um determinado ponto no tempo e pode até não ser precisa se outros processos estiverem gravando na tabela, a menos que você coloque um bloqueio de tabela na consulta.
Steve Ford

2
Você poderia usar inserir e excluir gatilhos para manter uma contagem contínua?
Paparazzo

Respostas:


246

Resposta simples:

  • Solução independente de fornecedor de banco de dados = use o padrão = COUNT(*)
  • Existem soluções aproximadas do SQL Server, mas não use COUNT (*) = fora do escopo

Notas:

COUNT (1) = COUNT (*) = COUNT (PrimaryKey) apenas no caso

Editar:

Exemplo do SQL Server (1,4 bilhões de linhas, 12 colunas)

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

1 execuções, 5:46 minutos, contagem = 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 execuções, ambas com menos de 1 segundo, contagem = 1.401.659.670

O segundo tem menos linhas = errado. Seria o mesmo ou mais, dependendo das gravações (as exclusões são feitas fora de horas aqui)


9
Não COUNT(*) = COUNT(key). Isso está errado. Se não houver NOT NULLrestrição - eles não poderão ser iguais (nos resultados e no plano de execução).
Zerkms

14
@zerkmsby: Para COUNT (chave), eu quis dizer COUNT (chave primária), que deve ser não anulável. Vou esclarecer
gbn

8
with (NOLOCK) não é algo que permita a execução na produção e pode levar a uma contagem imprecisa. Ao usar essa dica, verifique se ela impede bloqueios, mas os efeitos colaterais em uma caixa de produção são que você pode contar linhas duas vezes em algumas situações ou pular linhas em outras situações. É melhor usar NOLOCK em uma tabela que não está sendo gravada porque permite "leituras sujas". Não aconselho as pessoas a usar essa dica a menos que compreender totalmente as conseqüências
Davos

4
@mishrsud A única consulta precisa é a CONTAGEM SELECIONADA (*), mas é lenta. Você pode ter exatamente e lento, ou áspero e rápido. O que você faz dependerá do que é mais importante para o propósito para o qual você precisa contar. NO LOCK pode incluir ou excluir linhas que estão no meio da transação ou que movem páginas por qualquer motivo.
Davos

5
@gbn solução muito boa, você pode dizer o que é uso index_id < 2?
comprometa

29

A maneira mais rápida de longe no MySQL é:

SHOW TABLE STATUS;

Você receberá instantaneamente todas as suas tabelas com a contagem de linhas (que é o total), juntamente com muitas informações extras, se desejar.


1
Maneira inteligente .. com isso, você pode obter a contagem de linhas de várias tabelas em uma consulta.
Deval Khandelwal

você rodou no db com tabelas com ~ bilhões de entradas como @gbn e notou a hora?
KNU

qual valor é a contagem total de linhas para todas as tabelas no banco de dados? E estes são aproximados - e se você quiser valores exatos de contagem de linhas?
Kreeverp

2
isso não funciona, no INNODB, por exemplo, o mecanismo de armazenamento lê algumas linhas e extrapola para adivinhar o número de linhas
Martijn Scheffer

10

Encontrei artigos que afirmam que SELECT COUNT (*) FROM TABLE_NAME ficará lento quando a tabela tiver muitas linhas e muitas colunas.

Isso depende do banco de dados. Algumas aceleram a contagem, por exemplo, controlando se as linhas estão ativas ou não no índice, permitindo uma varredura de índice apenas para extrair o número de linhas. Outros não, e consequentemente exigem visitar a tabela inteira e contar linhas dinâmicas uma a uma. Ou será lento para uma mesa enorme.

Observe que geralmente você pode extrair uma boa estimativa usando ferramentas de otimização de consulta, estatísticas de tabela, etc. No caso do PostgreSQL, por exemplo, você pode analisar a saída explain count(*) from yourtablee obter uma estimativa razoavelmente boa do número de linhas. O que me leva à sua segunda pergunta.

Eu tenho uma tabela que pode conter até bilhões de linhas [tem aproximadamente 15 colunas]. Existe uma maneira melhor de obter a contagem EXATA do número de linhas de uma tabela?

Seriamente? :-) Você realmente quer dizer a contagem exata de uma tabela com bilhões de linhas? Tens mesmo a certeza? :-)

Se você realmente fizer isso, poderá manter um rastreamento do total usando gatilhos, mas lembre-se da simultaneidade e dos impasses.


Sim Denis, a contagem exata é necessária. :(
Swaranga Sarma

5
É uma sorte que os gerentes do Google sejam mais razoáveis ​​do que seu chefe ... Imagine como seria lento se retornasse o número exato de resultados de pesquisa para cada uma das suas consultas, em vez de se ater a um número estimado.
Denis de Bernardy

Pelo menos você simpatiza comigo. Que tal uma única solução Oracle? Isso reduzirá meu problema a uma extensão. Atualmente, o cliente está usando Oracle; portanto, se eu apresentar uma solução alternativa apenas para a Oracle, isso funcionará [por enquanto]. :)
Swaranga Sarma

6
"Sim Denis, a contagem exata é necessária. :(" - bem, só posso especular. O processo de manutenção de banco de dados descobre que existem 42.123.876 linhas na tabela A e, em seguida, cria 42.123.876 linhas vazias na tabela B e, em seguida, percorre a tabela a e atualizar as linhas na tabela B ... Ou é mais louco do que ;-)?
Tony Andrews

1
A transação 2 não pode começar antes que a transação 1 seja confirmada. Sem a atualização da "tabela de contagens", muitas transações de atualização poderiam ser executadas em paralelo. Com a "tabela de contagens", cada transação deve "obter um ticket" para atualizar sua contagem. Portanto, as transações começam a ser enfileiradas na máquina de tickets (o planejador decide quem será o próximo a obter um bloqueio na tabela de contagens).
precisa saber é o seguinte

10

Existe uma maneira melhor de obter a contagem EXATA do número de linhas de uma tabela?

Para responder sua pergunta simplesmente, não .

Se você precisar de uma maneira independente de DBMS de fazer isso, a maneira mais rápida será sempre:

SELECT COUNT(*) FROM TableName

Alguns fornecedores de DBMS podem ter maneiras mais rápidas de funcionar apenas para seus sistemas. Algumas dessas opções já foram publicadas em outras respostas.

COUNT(*) deve ser otimizado pelo DBMS (pelo menos qualquer banco de dados com valor de PROD) de qualquer maneira, portanto, não tente ignorar as otimizações.

Em uma nota lateral:
Tenho certeza de que muitas de suas outras consultas também levam muito tempo para serem concluídas devido ao tamanho da sua tabela. Provavelmente, qualquer preocupação com o desempenho deve ser resolvida pensando no design do seu esquema tendo em mente a velocidade. Sei que você disse que não é uma opção de alteração, mas pode acontecer que consultas com mais de 10 minutos também não sejam uma opção. A 3ª NF nem sempre é a melhor abordagem quando você precisa de velocidade e, às vezes, os dados podem ser particionados em várias tabelas se os registros não precisarem ser armazenados juntos. Algo para pensar sobre...


10

Eu recebi esse script de outra pergunta / resposta do 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);

Minha tabela possui 500 milhões de registros e os retornos acima em menos de 1 ms. Entretanto,

SELECT COUNT(id) FROM MyTable

leva 39 minutos, 52 segundos!

Eles produzem exatamente o mesmo número de linhas (no meu caso, exatamente 519326012).

Não sei se esse sempre seria o caso.


Você pode adicionar um parâmetro para obter a contagem de linhas com esta consulta? Exemplo: Selecione COUNT (1) FROM TABLENAME WHERE ColumnFiled = '1' Com sua consulta?
VnDevil

Essa é a contagem - o número de linhas (registros) é a "contagem" neste caso. "500 milhões de registros" era um número aproximado e "519326012" era o número exato de linhas ou contagem. Linhas = registros = contagem.
JakeJ

9

Você pode tentar este sp_spaceused (Transact-SQL)

Exibe o número de linhas, espaço em disco reservado e espaço em disco usado por uma tabela, exibição indexada ou fila do Service Broker no banco de dados atual ou exibe o espaço em disco reservado e usado por todo o banco de dados.


Sp_spaceused não me fornece uma contagem aproximada?
Swaranga Sarma 20/05

1
FYI: Isso usa sys.dm_db_partition_stats internamente
gbn

6

Se a edição do SQL Server for 2005/2008, você poderá usar as DMVs para calcular a contagem de linhas em uma tabela:

-- 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 

Para o mecanismo de banco de dados do SQL Server 2000, os sysindexes funcionarão, mas é altamente recomendável evitar usá-lo em edições futuras do SQL Server, pois ele pode ser removido no futuro próximo.

Código de exemplo extraído de: Como obter contagens de linhas da tabela de maneira rápida e indolor


Esta é aproximado não exata : ver a minha resposta, por favor
GBN

Você conhece um exemplo em que isso não é exato? AFAIK, não depende de estatísticas atualizadas.
Alireza Maddah 20/05

5

eu uso

select /*+ parallel(a) */  count(1) from table_name a;

Selecione / * + paralelo (a) * / count (1) de table_name a
Mainsh S

5

Não sou tão experiente quanto os outros que responderam, mas estava tendo um problema com um procedimento que estava usando para selecionar uma linha aleatória de uma tabela (não muito relevante), mas precisava saber o número de linhas na minha tabela de referência para calcular o índice aleatório. Usando o trabalho tradicional Count (*) ou Count (1), eu ocasionalmente levava 2 segundos para executar minha consulta. Então, em vez disso (para minha tabela chamada 'tbl_HighOrder'), estou usando:

Declare @max int

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

Funciona muito bem e os tempos de consulta no Management Studio são zero.


1
FWIW, você deve mencionar QUAL fornecedor de banco de dados você está usando; Eu acho que a declaração seria um pouco diferente dependendo do fornecedor.
Página Inicial>

5

Bem, atrasado 5 anos e não tenho certeza se isso ajuda:

Eu estava tentando contar o não. de linhas em uma tabela do SQL Server usando o MS SQL Server Management Studio e ocorreu algum erro de estouro, então usei o abaixo:

selecione count_big (1) FROM [dbname]. [dbo]. [FactSampleValue];

O resultado :

24296650578 linhas


5

Encontrei este bom artigo SQL Server – HOW-TO: recupere rapidamente a contagem precisa de linhas da tabela, a partir da martijnh1qual é possível recapitular cada cenário.

Preciso que isso seja expandido, onde forneça uma contagem com base em uma condição específica e, quando descobrir esta parte, atualizarei mais essa resposta.

Enquanto isso, aqui estão os detalhes do artigo:

Método 1:

Inquerir:

SELECT COUNT(*) FROM Transactions 

Comentários:

Executa uma verificação completa da tabela. Lento em mesas grandes.

Método 2:

Inquerir:

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

Comentários:

Maneira rápida de recuperar a contagem de linhas. Depende das estatísticas e é impreciso.

Execute DBCC UPDATEUSAGE (banco de dados) WITH COUNT_ROWS, que pode levar um tempo significativo para tabelas grandes.

Método 3:

Inquerir:

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')) 

Comentários:

A maneira como o SQL Management Studio conta linhas (veja as propriedades da tabela, armazenamento, contagem de linhas). Muito rápido, mas ainda assim um número aproximado de linhas.

Método 4:

Inquerir:

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

Comentários:

Operação rápida (embora não tão rápida quanto o método 2) e igualmente importante, confiável.


Obrigado! Dica realmente útil. Eu não tenho permissão para visualizar tabelas do sistema, portanto o método 4 não sou eu. No entanto, o método 3 é bom o suficiente.
Nicholas Humphrey

3

Eu não acho que exista uma solução geral sempre mais rápida: algumas versões do RDBMS / têm uma otimização específica para SELECT COUNT(*)usar opções mais rápidas, enquanto outras simplesmente fazem a varredura de tabela. Você precisaria ir aos sites de documentação / suporte para o segundo conjunto, que provavelmente precisará de alguma consulta mais específica para ser escrita, geralmente uma que atinja um índice de alguma forma.

EDITAR:

Aqui está um pensamento que pode funcionar, dependendo do seu esquema e distribuição dos dados: você tem uma coluna indexada que faz referência a um valor crescente, um ID numérico crescente, por exemplo, ou mesmo um carimbo de data / hora? Então, supondo que as exclusões não ocorram, deve ser possível armazenar a contagem até algum valor recente (data de ontem, valor mais alto de ID em algum ponto recente da amostra) e adicionar a contagem além disso, o que deve ser resolvido muito rapidamente no índice . Muito dependente de valores e índices, é claro, mas aplicável a praticamente qualquer versão de qualquer DBMS.


Eu esperava muito que qualquer SGBD decente usasse um índice para SELECT COUNT(*). Até o MySQL aparentemente faz isso.
sleske

assumindo exclusões não acontecem - a sério? ; p
ToolmakerSteve

3

Estou atrasado para esta pergunta, mas aqui está o que você pode fazer com o MySQL (como eu uso o MySQL). Estou compartilhando minhas observações aqui:

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

Resultado
Contagem de linhas: 508534
Saída do console: linhas afetadas: 0 linhas encontradas: 1 avisos: 0 duração para 1 consulta: 0.125 seg.
Demora um tempo para uma tabela com grande número de linhas, mas a contagem de linhas é muito exata.

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

Resultado
Contagem de linhas: 511235
Saída do console : Linhas afetadas: 0 Linhas encontradas: 1 Avisos: 0 Duração para 1 consulta: 0,250 s Resumo: A contagem de linhas não é exata.

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

Resultado
Contagem de linhas: 507806
Saída do console : Linhas afetadas: 0 Linhas encontradas: 48 Avisos: 0 Duração para 1 consulta: 1.701 seg.
A contagem de linhas não é exata.

Não sou especialista em MySQL ou em banco de dados, mas descobri que, para tabelas muito grandes, você pode usar a opção 2 ou 3 e obter uma 'boa idéia' de quantas linhas estão presentes.

Eu precisava obter essas contagens de linha para exibir algumas estatísticas na interface do usuário. Com as consultas acima, eu sabia que o total de linhas era superior a 500.000, por isso criei estatísticas como "Mais de 500.000 linhas" sem mostrar o número exato de linhas.

Talvez eu realmente não tenha respondido à pergunta do OP, mas estou compartilhando o que fiz em uma situação em que essas estatísticas eram necessárias. No meu caso, mostrar as linhas aproximadas era aceitável e, portanto, o acima funcionou para mim.


2

Não é exatamente uma solução independente de DBMS, mas pelo menos o código do seu cliente não verá a diferença ...

Crie outra tabela T com apenas uma linha e um campo inteiro N 1 e crie INSERT TRIGGER que apenas executa:

UPDATE T SET N = N + 1

Crie também um DELETE TRIGGER que executa:

UPDATE T SET N = N - 1

Um DBMS digno de seu sal garantirá a atomicidade das operações acima de 2 , e N conterá a contagem precisa de linhas em todos os momentos, o que é super rápido para simplificar:

SELECT N FROM T

Embora os acionadores sejam específicos do DBMS, a seleção de T não é e o código do seu cliente não precisará ser alterado para cada DBMS suportado.

No entanto, isso pode ter alguns problemas de escalabilidade se a tabela for intensiva em INSERT ou DELETE, especialmente se você não confirmar imediatamente após INSERT / DELETE.


1 Esses nomes são apenas espaços reservados - use algo mais significativo na produção.

2 Ie N não pode ser alterado por uma transação simultânea entre leitura e gravação para N, desde que a leitura e a gravação sejam feitas em uma única instrução SQL.


2

Uma resposta literalmente insana, mas se você tiver algum tipo de sistema de replicação configurado (para um sistema com um bilhão de linhas, espero que sim), você pode usar um estimador aproximado (como MAX(pk)), dividir esse valor pelo número de escravos você tem, execute várias consultas em paralelo.

Na maioria das vezes, você particionaria as consultas entre os escravos com base na melhor chave (ou na chave primária, eu acho), de tal maneira (usaremos 250000000 como nossas Linhas / escravos):

-- 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

Mas você precisa apenas de SQL. Que busto. Ok, então vamos dizer que você é um sadomasoquista. No mestre (ou escravo mais próximo), você provavelmente precisará criar uma tabela para isso:

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

Portanto, em vez de ter apenas os seletores em execução em seus escravos, você teria que fazer uma inserção, semelhante a isso:

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

Você pode ter problemas com os escravos escrevendo para uma tabela no mestre. Você pode precisar ficar ainda mais triste - quero dizer, criativo:

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

No final, você deve ter um escravo que exista por último no caminho percorrido pelo gráfico de replicação, em relação ao primeiro escravo. Esse escravo agora deve ter todos os outros valores de contador e deve ter seus próprios valores. Porém, quando você terminar, provavelmente haverá linhas adicionadas; portanto, você deverá inserir outra para compensar o valor máximo de gravação registrado na sua counter_table e o valor máximo de atualização atual.

Nesse ponto, você teria que fazer uma função agregada para descobrir qual é o total de linhas, mas isso é mais fácil, pois você a executaria no máximo com o "número de escravos que você possui e altera".

Se você estiver na situação em que possui tabelas separadas nos escravos, poderá UNIONobter todas as linhas necessárias.

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

Ou você sabe, seja um pouco menos insano e migre seus dados para um sistema de processamento distribuído, ou talvez use uma solução Data Warehousing (que também fornecerá dados impressionantes no futuro).

Observe que isso depende de quão bem sua replicação está configurada. Como o gargalo primário provavelmente será o armazenamento persistente, se você tiver armazenamento bruto ou armazenamentos de dados mal segregados com alto ruído do vizinho, provavelmente será mais lento do que apenas esperar por um únicoSELECT COUNT(*) ...

Mas se você tiver uma boa replicação, seus ganhos de velocidade deverão estar diretamente relacionados ao número ou escravos. De fato, se levar 10 minutos para executar a consulta de contagem sozinho e você tiver 8 escravos, reduzirá seu tempo para menos de alguns minutos. Talvez uma hora para resolver os detalhes desta solução.

Obviamente, você nunca obteria uma resposta incrivelmente precisa, pois essa solução distribuída introduz um pouco de tempo em que as linhas podem ser excluídas e inseridas, mas você pode tentar obter um bloqueio distribuído de linhas na mesma instância e obter uma contagem precisa das linhas da tabela por um momento específico.

Na verdade, isso parece impossível, já que você está basicamente preso a uma solução somente para SQL e não acho que tenha fornecido um mecanismo para executar uma consulta fragmentada e bloqueada em vários escravos, instantaneamente. Talvez se você tivesse o controle do arquivo de log de replicação ... o que significa que você literalmente criaria escravos para esse fim, o que é sem dúvida mais lento do que executar a consulta de contagem em uma única máquina de qualquer maneira.

Então, há meus dois centavos de 2013.


2

Se o gatilho de inserção for muito caro de usar, mas um gatilho de exclusão puder ser fornecido, e houver um incremento automáticoid , depois de contar a tabela inteira uma vez e lembrar a contagem como last-counte last-counted-id,

então todos os dias precisam contar id> last-counted-id, adicionar last-counte armazenar o novo last-counted-id.

O gatilho de exclusão diminuiria a última contagem, se o ID do registro excluído <= último-contado-id.


.. desculpe, não tenho tempo para mostrar o SQL que seria usado (meu SQL está enferrujado). Se alguém quiser editar minha resposta para adicionar SQL, isso seria ótimo!
Home

1

Se você tiver uma estrutura de tabela típica com uma coluna de chave primária de incremento automático na qual as linhas nunca são excluídas, a seguir será a maneira mais rápida de determinar a contagem de registros e deve funcionar de maneira semelhante na maioria dos bancos de dados compatíveis com ANSI:

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

Trabalho com tabelas do MS SQL que contêm bilhões de linhas que requerem tempos de resposta em segundos para dados, incluindo contagens de registros. Uma CONTAGEM SELECIONADA semelhante (*) levaria alguns minutos para ser processada por comparação.


1
Não é inteiramente verdade - e se uma INSERTtransação for revertida? Esse valor da chave primária estaria ausente, portanto, a contagem real de registros seria um a menos que o valor máximo.
Sir Crispalot

Pode haver lacunas na sequência. Geralmente, resultado de reversões.
Osa E

Na verdade, há uma modificação dessa resposta que pode ser significativamente mais rápida do que count(*), se um fornecedor de banco de dados não tiver sido suficientemente otimizado count(*): Todos os dias, acompanhe o último índice automático e sua contagem correspondente e peça uma contagem de registros além disso. Também pode lidar com deletes se adicionar um gatilho na exclusão que diminua o total anterior , se o ID do registro excluído <= esse último índice automático.
Home

1

Para servidor Sql, tente isso

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

selecione linhas de sysindexes em que id = Object_ID ('TableName') e indid <2


0

Coloque um índice em alguma coluna. Isso deve permitir que o otimizador execute uma varredura completa dos blocos de índice, em vez de uma varredura completa da tabela. Isso reduzirá seus custos de IO. Veja o plano de execução antes e depois. Meça o tempo do relógio de parede nos dois sentidos.


Se uma tabela tiver bilhões de linhas sem um índice em qualquer coluna, haverá problemas de desempenho generalizados, muito além da necessidade expressa na pergunta original .. mas é bom que você mencione isso (não assuma nada!) :)
ToolmakerSteve

0

Se você estiver usando o Oracle, que tal isso (supondo que as estatísticas da tabela sejam atualizadas):

select <TABLE_NAME>, num_rows, last_analyzed from user_tables

last_analyzed mostrará a hora em que as estatísticas foram coletadas pela última vez.


0

Com o PostgreSQL:

SELECT reltuples AS approximate_row_count FROM pg_class WHERE relname = 'table_name'

-1

No SQL Server 2016, posso apenas verificar as propriedades da tabela e selecionar a guia 'Armazenamento' - isso fornece contagem de linhas, espaço em disco usado pela tabela, espaço de índice usado etc.


Ele estava procurando por database vendor independent solution. Além disso, isso requer uma GUI e não pode ser automatizado. Também não é mais rápido como COUNT (*)
Frieder

-3

Talvez um pouco tarde, mas isso pode ajudar outras pessoas no MSSQL

; WITH RecordCount AS (SELECT ROW_NUMBER () OVER (ORDER BY COLUMN_NAME) AS [RowNumber] FROM TABLE_NAME) SELECT MAX (RowNumber) FROM RecordCount


Isso é significativamente pior que COUNT (), a menos que tenhamos muita sorte e o otimizador consiga otimizá-lo para COUNT () - por que pedir para classificar em uma coluna aleatória?!?
DSZ
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.