Meu aplicativo depende da execução de "mostrar colunas" para determinadas tabelas. Demora cerca de 60ms para ser executado, enquanto todas as outras consultas levam menos de um ms. Consultar information_schema
diretamente é ainda mais lento.
O banco de dados contém cerca de 250 bancos de dados, com 100 a 200 tabelas por banco de dados (cerca de 20k tabelas no total).
- Como posso descobrir por que essas operações são tão lentas?
- Talvez exista alguma configuração que eu possa alterar para torná-lo mais rápido ou armazená-lo em cache no lado do SQL?
(O aplicativo faz cerca de 14 consultas desse tipo por carregamento de página - estou ciente de que esse código herdado precisa ser limpo, mas procurando por opções possíveis enquanto trabalho na correção de longo prazo.)
Respostas:
O MySQL recalcula as estatísticas da tabela para certas operações que acessam
INFORMATION_SCHEMA
tabelas (SHOW COLUMNS
é apenas um alias conveniente para consultaINFORMATION_SCHEMA.COLUMNS
). Defina innodb_stats_on_metadata como false, o que impedirá que esse recálculo ocorra quando você solicitar metadados da tabela.e adicione o seguinte a
my.cnf
fonte
[mysqld]
lá. Pode ser óbvio para muitos que essa configuração se enquadra no mysqld, mas pode não ser óbvio para aqueles que fazem essa pergunta. By the way, isso acelerouSELECT COUNT(*)
em uma das minhasinformation_schema
mesas para 6 segundos a partir de mais de um minuto. Ainda lento, mas uma enorme melhoria.Eu sugiro que você crie um banco de dados que tenha as
INFORMATION_SCHEMA
tabelas (ou apenas as que você precisa) como réplicas. Indexá-los adequadamente e você terá ganho de desempenho.O problema de sincronizar entre esse banco de dados e
INFORMATION_SCHEMA
é complicado.Você pode ter um procedimento que sincronize essas tabelas a cada hora ou a cada 5 minutos (com que frequência a estrutura das tabelas é alterada?).
Outra idéia seria usar o MySQL Proxy para capturar quaisquer
ALTER TABLE
instruções (eCREATE
/DROP
eCREATE INDEX
quaisquer outras instruções que modifiquem as informações necessárias) e sincronizar o esquema de informações replicadas após o êxito dessas instruções.Se você precisar apenas dos nomes das colunas e de nenhuma outra informação, como tipo de dados, comprimento ou índices disponíveis, talvez possa substituir o uso de
SHOW COLUMNS
consultas (rápidas) que retornam apenas 1 linha, comLIMIT 1
ou nenhuma, comLIMIT 0
ou:Apesar dos conselhos gerais contra o uso de
SELECT *
, este pode ser um caso legítimo em que nada mais é útil. (tudo o resto*
, pode resultar em erro!)fonte
Nesse caso em particular, acho que
INFORMATION_SCHEMA
é um arenque vermelho. Nos meus próprios testes deSHOW COLUMNS
desempenho, ainnodb_stats_on_metadata
variável parece não fazer diferença nas tabelas MyISAM ou InnoDB.No entanto, no manual do MySQL 5.0 ...
Isso parece ter sido removido do manual a partir do MySQL 5.5, mas ainda parece se aplicar nessa versão ...
As informações de campo retornadas com um conjunto de resultados da consulta contêm as mesmas informações retornadas por
SHOW COLUMNS
, portanto,SELECT * FROM my_table LIMIT 0
deve-se obter a mesma coisa sem criar uma tabela temporária em disco por consulta.Um exemplo rápido para apenas pegar os nomes dos campos em PHP ...
Recuperar informações de campo dessa maneira é um pouco mais difícil de decodificar. Você precisará consultar a descrição da
MYSQL_FIELD
estrutura subjacente para obter os tipos e sinalizadores de dados, mas ela é executada cerca de 7 vezes mais rápido no meu sistema.fonte
Gosto da primeira sugestão na resposta de @ yerpcube (+1), mas gostaria de propor algo
--no-data
--routines
--triggers
--all-databases
ou--databases
seguido por uma lista de bancos de dados que você desejaAssim, o mysqldump deve ter a seguinte aparência:
É isso aí. A partir de agora, tudo o que você precisa fazer é conectar-se a esta instância do banco de dados da porta 3307 e executar qualquer consulta relacionada ao esquema ao conteúdo do seu coração. Se você souber de alguma tabela no banco de dados de produção que seja alterada, apenas mysqldump o esquema da produção e recarregue-o novamente na instância da porta 3307.
AVISO: Se você instalar uma instância do mysql na mesma máquina que a produção, certifique-se de se conectar a essa instância usando
Se você executar
Mangueira produção. Por isso tem cuidado !!!!
Uma alternativa seria usar apenas um servidor de banco de dados separado.
fonte