Ir para conteúdo
Fórum Script Brasil
  • 0

SELECT COUNT em tabela InnoDB


Andréa Carvalho

Pergunta

SELECT COUNT está muito lento.....aí descobri que isso é uma caracteristica das tabelas InnoDB, lendo o manual do MySQL:

InnoDB does not keep an internal count of rows in a table. (In practice, this would be somewhat complicated due to multi-versioning.) To process a SELECT COUNT(*) FROM t statement, InnoDB must scan an index of the table, which takes some time if the index is not entirely in the buffer pool. To get a fast count, you have to use a counter table you create yourself and let your application update it according to the inserts and deletes it does. If your table does not change often, using the MySQL query cache is a good solution. SHOW TABLE STATUS also can be used if an approximate row count is sufficient.

http://dev.mysql.com/doc/refman/5.0/en/inn...strictions.html

SHOW TABLE STATUS não é uma opção boa pra mim.....dentre as outras 2 opções que eles sugerem..... qual deverá ser mais vantajosa? Alguém tem alguma outra alternativa???

Editado por Andréa Carvalho
Link para o comentário
Compartilhar em outros sites

6 respostass a esta questão

Posts Recomendados

  • 0

Oi Denis,

Li o link que você passou, mas minha tabela é InnoDB, ela funciona diferente da MyISAM, como vi no manual ela não tem uma contagem interna dos registros da tabela como tem na MyISAM, por isso o count é mais lento.

E sobre usar a alternativa de criar tabela contadora, achei q não teria problema, mas agora que analizei melhor, acho q tb não seria uma boa solução, porque preciso dar SELECT COUNT em queries dinâmicas com vários JOINS.... e não teria como criar uma tabela contadora para cada situação.....

A outra alternativa que encontrei no manual é essa:"using the MySQL query cache is a good solution". Como usar esse cache do MySQL query??? E você tem alguma outra alternativa além dessas que o manual aconselha?

Obrigada!!!

Editado por Andréa Carvalho
Link para o comentário
Compartilhar em outros sites

  • 0

Nos tópicos relacionados daquele link q você me passou, encontrei esse link http://www.mysqlperformanceblog.com/2006/1...-innodb-tables/ que fala sobre count em tabelas InnoDB, e parece que para o meu caso, que é um SELECT COUNT com WHERE, o count é lento até mesmo nas tabelas MyISAM.....hehehe porque elas tb tem q percorrer a tabela td pra contar os registros....

E agora? o que eu faço?? :o

Link para o comentário
Compartilhar em outros sites

  • 0

Oi, Andréa,

Lembra quando falei sobre Views físicas (materializadas) no tópico Melhorar performance do MySQL? Verifique se a atualização dos dados query é contante. Se não for, vale a pena criar a view não como temporary table como sugeri no tópico anterior, mas como tabela física na engine MyISAM.

Link para o comentário
Compartilhar em outros sites

  • 0

Oi, 'Andréa Carvalho'

Uma outra opção, que andei buscando foi de forçar o uso de indices para o count.

Veja esta matéria InnoDB Row Counting using Indexes

Principalmente esta parte

31: mysql> SELECT COUNT(*) FROM test;  
32: +----------+  
33: | COUNT(*) |  
34: +----------+  
35: |   300000 |  
36: +----------+  
37: 1 row in set (1.08 sec)  
38:    
39: mysql> SELECT COUNT(*) FROM test use index (int_k);  
40: +----------+  
41: | COUNT(*) |  
42: +----------+  
43: |   300000 |  
44: +----------+  
45: 1 row in set (0.12 sec)

Note que há um ganho significativo no tempo quando se usa um índice secundário em lugar do índice primário.

Citando a primeira resposta ao primeiro um comment

Good point. It has to go back to the primary key, not primary index. Remember, the cost of scanning the primary index is primarylen+rowlen, but for secondary index it is secondarylen+primarylen. The calculation by Heikki, cited in the post, shows that it is a good bet to scan secondary index in this

case.

Link para o comentário
Compartilhar em outros sites

  • 0

Oi Denis,

Antes de tudo muito obrigada! ;)

Não sei se é possível, ou se ganharia alguma performance no meu caso, porque o meu count não é em uma única tabela, por exemplo:

SELECT count(*) AS count FROM vtiger_salesorder FORCE INDEX(PRIMARY)
INNER JOIN vtiger_crmentity ON vtiger_crmentity.crmid = vtiger_salesorder.salesorderid 
WHERE vtiger_crmentity.deleted = 0

Entendeu?? Tentei usar um índice secundário da tabela vtiger_salesorder e outra hora um da tabela vtiger_crmentity, mas me parece não fazer diferença..... porque não consigo criar um campo ordenado, como ele criou no exemplo, pois dependendo das tabelas que irei mesclar, a ordem é diferente..... :huh:

Ainda estou estudando a outra idéia q você me deu....de criar uma view temporária.....

Se você ou mais alguém do fórum tiver mais alguma idéia ou dica, estou toda a ouvidos!!!

Obrigadaaaaa

Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novos posts.


  • Estatísticas dos Fóruns

    • Tópicos
      152,3k
    • Posts
      652,5k
×
×
  • Criar Novo...