{"id":21010,"date":"2026-08-26T08:33:40","date_gmt":"2026-08-26T06:33:40","guid":{"rendered":"https:\/\/webhosting.de\/mysql-explain-analyze-abfragen-interpretieren-query-tuning\/"},"modified":"2026-08-26T08:33:40","modified_gmt":"2026-08-26T06:33:40","slug":"interpretar-consultas-mysql-explain-e-analyze-otimizacao-de-consultas","status":"publish","type":"post","link":"https:\/\/webhosting.de\/pt\/mysql-explain-analyze-abfragen-interpretieren-query-tuning\/","title":{"rendered":"MySQL EXPLAIN ANALYZE: Interpretar corretamente as consultas para obter o m\u00e1ximo desempenho"},"content":{"rendered":"<p>Com o `mysql explain`, analiso como o MySQL 8 cria um plano <strong>executa<\/strong> e quais os passos que consomem tempo de forma mensur\u00e1vel. Assim, com base em tempos de execu\u00e7\u00e3o reais, n\u00fameros de linhas e loops, consigo identificar onde devo ajustar um plano e a <strong>Desempenho<\/strong> aumentar de forma espec\u00edfica o n\u00famero das minhas consultas.<\/p>\n\n<h2>Pontos centrais<\/h2>\n\n<p>Para que possas ir direto ao essencial, vou resumir brevemente os principais objetivos de aprendizagem e definir os <strong>Prioridades<\/strong>. Cada linha do plano conta uma hist\u00f3ria, e eu mostro-te o que realmente <strong>respeitavas<\/strong>. L\u00ea os pontos, analisa as tuas consultas e aplica os conhecimentos adquiridos diretamente em passos de otimiza\u00e7\u00e3o.<\/p>\n<ul>\n  <li><strong>Tempos reais de execu\u00e7\u00e3o<\/strong>: O EXPLAIN ANALYZE executa a consulta e mede os tempos por cada etapa.<\/li>\n  <li><strong>Estimativas vs. realidade<\/strong>: Grandes desvios indicam estat\u00edsticas incorretas ou a aus\u00eancia de \u00edndices.<\/li>\n  <li><strong>Formato TREE<\/strong>: O plano em forma de \u00e1rvore torna vis\u00edveis os iteradores, os filtros e as jun\u00e7\u00f5es.<\/li>\n  <li><strong>Pontos de acesso<\/strong>: Um \u201etime to last row\u201c longo e muitos loops indicam os objetivos de afina\u00e7\u00e3o.<\/li>\n  <li><strong>Estrat\u00e9gia de \u00edndice<\/strong>: Os \u00edndices adequados (incluindo os compostos) reduzem significativamente os custos.<\/li>\n<\/ul>\n<p>A lista d\u00e1-te uma vis\u00e3o clara <strong>dire\u00e7\u00e3o<\/strong>, mas s\u00f3 ao ler o plano na pr\u00e1tica \u00e9 que pones esse conhecimento em pr\u00e1tica de forma proveitosa. Em seguida, mostro-te como avalio cada indicador e quais os pr\u00f3ximos passos <strong>Passos<\/strong> concluo disso.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img fetchpriority=\"high\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/08\/mysql-analyse-buero-8723.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>EXPLAIN vs. EXPLAIN ANALYZE: O que estou realmente a medir<\/h2>\n\n<p>Com o EXPLAIN cl\u00e1ssico, consigo ver o percurso planeado pelo otimizador, ou seja, um <strong>Esbo\u00e7o<\/strong> com custos estimados e n\u00famero de linhas. Este plano revela a ordem das tabelas, os \u00edndices utilizados e a estrat\u00e9gia de jun\u00e7\u00e3o, embora sem uma verdadeira <strong>Valores medidos<\/strong>. O EXPLAIN ANALYZE continua e executa efetivamente a consulta, medindo os tempos at\u00e9 \u00e0 primeira e \u00e0 \u00faltima linha, bem como os ciclos. Desta forma, consigo identificar imediatamente qual o n\u00f3 da \u00e1rvore que consome mais tempo e por onde devo come\u00e7ar. Assim, substituo suposi\u00e7\u00f5es por dados medidos <strong>Dados<\/strong> e tomar decis\u00f5es de otimiza\u00e7\u00e3o bem fundamentadas.<\/p>\n\n<h2>Sintaxe e casos de utiliza\u00e7\u00e3o t\u00edpicos<\/h2>\n\n<p>Come\u00e7o a an\u00e1lise com um comando simples: <code>EXPLAIN ANALYZE SELECT ...<\/code>, porque assim consigo, de imediato, <strong>Tempos de funcionamento<\/strong> por cada n\u00f3. A sa\u00edda no formato TREE apresenta iteradores como varreduras, jun\u00e7\u00f5es, ordena\u00e7\u00f5es e filtros com valores estimados e reais <strong>Linhas<\/strong>. Utilizo isto especialmente para consultas recorrentes sobre problemas, opera\u00e7\u00f5es UPDATE\/DELETE em v\u00e1rias tabelas e para instru\u00e7\u00f5es com ORDER BY ou GROUP BY. Opcionalmente, ajuda-me <code>FORMATO=JSON<\/code>, se quiser analisar em profundidade o modelo de custos, mas, para ajustes no dia a dia, a \u00e1rvore \u00e9, na maioria das vezes, suficiente. Quem quiser aprofundar-se em quest\u00f5es relacionadas com o Optimizer encontrar\u00e1 boas sugest\u00f5es em <a href=\"https:\/\/webhosting.de\/pt\/mysql-optimizer-query-hosting-otimizacao-serverboost\/\">Detalhes do otimizador<\/a>, que utilizo na pr\u00e1tica.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/08\/mysql_meeting_9245.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>\u00c9 assim que interpreto o plano TREE<\/h2>\n\n<p>Considero cada n\u00f3 como um passo independente que produz dados ou <strong>filtra<\/strong>. As opera\u00e7\u00f5es de varredura fornecem linhas a partir de tabelas ou \u00edndices, as jun\u00e7\u00f5es ligam fluxos, os filtros reduzem o n\u00famero de linhas e as ordena\u00e7\u00f5es organizam ou agrupam as <strong>Resultados<\/strong>. Os campos \u201erows (actual\/estimated)\u201c, \u201etime to first row\u201c, \u201etime to last row\u201c e \u201eloops\u201c s\u00e3o os meus principais indicadores. Se o n\u00famero real de linhas diferir significativamente da estimativa, corrijo as estat\u00edsticas ou os \u00edndices. Se o \u201etime to last row\u201c se prolongar excessivamente, verifico se h\u00e1 ordena\u00e7\u00f5es tardias, jun\u00e7\u00f5es de grandes dimens\u00f5es ou <strong>Filtros<\/strong>.<\/p>\n\n<h2>Compreender os indicadores-chave: da estimativa \u00e0 realidade<\/h2>\n\n<p>Vou resumir os indicadores mais importantes numa tabela clara, para que possas identificar rapidamente os sinais t\u00edpicos <strong>reconhecer<\/strong>. Cada linha mostra-te o que significa uma m\u00e9trica, que sinal de alerta estou a observar e qual a medida que, na maioria das vezes, <strong>Ajudas<\/strong>.<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u00cdndice<\/th>\n      <th>Significado<\/th>\n      <th>sinal de alerta<\/th>\n      <th>Abordagem de afina\u00e7\u00e3o<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>linhas (estimado\/real)<\/td>\n      <td>Previstas vs. reais <strong>Linhas<\/strong><\/td>\n      <td>Grande diferen\u00e7a (por exemplo, 10 contra 100 000)<\/td>\n      <td>Atualizar as estat\u00edsticas, as que faltam <strong>\u00cdndices<\/strong> controlo<\/td>\n    <\/tr>\n    <tr>\n      <td>tempo at\u00e9 \u00e0 primeira linha<\/td>\n      <td>Tempo at\u00e9 \u00e0 primeira <strong>Quest\u00e3o<\/strong><\/td>\n      <td>Lento, apesar do n\u00famero reduzido de resultados<\/td>\n      <td>Verificar o n\u00f3 inicial, filtros iniciais <strong>refor\u00e7ar<\/strong><\/td>\n    <\/tr>\n    <tr>\n      <td>tempo at\u00e9 \u00e0 \u00faltima linha<\/td>\n      <td>Dura\u00e7\u00e3o total do <strong>N\u00f3s<\/strong><\/td>\n      <td>Bem mais alto do que a \u201eprimeira fila\u201c<\/td>\n      <td>Ordena\u00e7\u00e3o, estrat\u00e9gia de jun\u00e7\u00e3o, fluxos <strong>reduzir<\/strong><\/td>\n    <\/tr>\n    <tr>\n      <td>loops<\/td>\n      <td>Frequ\u00eancia da <strong>Repeti\u00e7\u00e3o<\/strong><\/td>\n      <td>Muitas itera\u00e7\u00f5es<\/td>\n      <td>Reorganizar jun\u00e7\u00f5es, subconsultas <strong>transformar<\/strong><\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/08\/mysql-explain-analyze-performance-8159.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Interpretar corretamente os operadores: varreduras, jun\u00e7\u00f5es, ordena\u00e7\u00f5es<\/h2>\n\n<p>Presto aten\u00e7\u00e3o ao que <strong>Iterador<\/strong> quem, na verdade, faz o trabalho:<\/p>\n<ul>\n  <li><strong>Intervalo de \u00edndice\/an\u00e1lise \u00fanica<\/strong>: Ideal para condi\u00e7\u00f5es WHERE seletivas e prefixos adequados; o \u201etempo at\u00e9 \u00e0 primeira linha\u201c \u00e9 reduzido, enquanto o \u201etempo at\u00e9 \u00e0 \u00faltima linha\u201c depende do conjunto de resultados.<\/li>\n  <li><strong>Varredura da tabela<\/strong>: Sinal de alerta em tabelas de grande dimens\u00e3o; nesse caso, procuro filtros adequados, \u00edndices compostos ou reformula\u00e7\u00e3o da consulta.<\/li>\n  <li><strong>Juntura de la\u00e7os aninhados<\/strong>: Estrat\u00e9gia padr\u00e3o; a presen\u00e7a de muitos \u201eloops\u201c indica um controlador inadequado ou a falta de um \u00edndice na tabela interna.<\/li>\n  <li><strong>Juntar por hash<\/strong> (MySQL 8): Adequado para equi-joins de grande dimens\u00e3o e uniformemente distribu\u00eddas. O \u201etime to first row\u201c pode ser mais elevado (fase de compila\u00e7\u00e3o), mas o \u201etime to last row\u201c beneficia quando o fluxo de dados de teste \u00e9 elevado.<\/li>\n  <li><strong>Ordenar<\/strong>\/<strong>Grupo<\/strong>: No TREE, s\u00e3o claramente vis\u00edveis como n\u00f3s pr\u00f3prios. Tempos de execu\u00e7\u00e3o elevados indicam frequentemente a falta de suporte por parte dos \u00edndices.<\/li>\n  <li><strong>Filtros<\/strong>: Os filtros tardios indicam oportunidades perdidas para o \u00abIndex Condition Pushdown\u00bb ou para uma sele\u00e7\u00e3o mais precoce.<\/li>\n<\/ul>\n<p>Se um n\u00f3 de ordena\u00e7\u00e3o dominar o \u201etime to last row\u201c, verifico se a ordena\u00e7\u00e3o pretendida pode ser obtida atrav\u00e9s de um \u00edndice, por exemplo, atrav\u00e9s de <strong>Cobertura<\/strong>- \u00cdndices com a ordem de ordena\u00e7\u00e3o adequada. Se a cl\u00e1usula ORDER BY corresponder \u00e0 defini\u00e7\u00e3o do \u00edndice (dire\u00e7\u00e3o, prefixo), a etapa de ordena\u00e7\u00e3o \u00e9, muitas vezes, totalmente dispensada.<\/p>\n\n<h2>Metodologia de avalia\u00e7\u00e3o: como fazer uma compara\u00e7\u00e3o justa<\/h2>\n\n<p>N\u00e3o fa\u00e7o a medi\u00e7\u00e3o apenas uma vez. Os efeitos de cache podem distorcer a impress\u00e3o, por isso:<\/p>\n<ul>\n  <li>Executo o comando EXPLAIN ANALYZE v\u00e1rias vezes e avalio a mediana e o intervalo, em vez de um \u00fanico valor.<\/li>\n  <li>Fa\u00e7o a distin\u00e7\u00e3o entre cache \u201efrio\u201c e \u201equente\u201c: as medi\u00e7\u00f5es \u00abquentes\u00bb mostram o que os utilizadores experimentam ap\u00f3s a primeira execu\u00e7\u00e3o.<\/li>\n  <li>Vario os par\u00e2metros representativos para que o plano n\u00e3o pare\u00e7a bom apenas num exemplo trivial.<\/li>\n  <li>Documento o esquema e o estado dos dados para poder compreender os resultados mais tarde.<\/li>\n<\/ul>\n<p>Nas instru\u00e7\u00f5es DML (UPDATE\/DELETE), utilizo uma transa\u00e7\u00e3o: <code>START TRANSACTION; EXPLAIN ANALYZE UPDATE ...; ROLLBACK;<\/code>. Assim, obtenho valores de medi\u00e7\u00e3o reais sem altera\u00e7\u00f5es permanentes. Importante: EXPLAIN ANALYZE <strong>conduz<\/strong> por isso, utilizo-o com cautela nos sistemas de produ\u00e7\u00e3o.<\/p>\n\n<h2>Estat\u00edsticas e distribui\u00e7\u00e3o de dados: corrigir erros de estimativa<\/h2>\n\n<p>As grandes diferen\u00e7as entre as linhas \u201eestimated\u201c e \u201eactual\u201c resultam frequentemente de distribui\u00e7\u00f5es de dados assim\u00e9tricas. Nesses casos, sigo uma dupla abordagem:<\/p>\n<ul>\n  <li><strong>Atualizar estat\u00edsticas<\/strong>: Asseguro-me de que o otimizador disponha de informa\u00e7\u00f5es atualizadas. Estat\u00edsticas recentes melhoram a escolha das jun\u00e7\u00f5es e dos \u00edndices.<\/li>\n  <li><strong>Utilizar histogramas<\/strong>: No caso de colunas com elevada assimetria, os histogramas ajudam a estimar as seletividades de forma mais realista. No EXPLAIN ANALYZE, a diferen\u00e7a entre a estimativa e a realidade diminui visivelmente.<\/li>\n<\/ul>\n<p>Se, ap\u00f3s a atualiza\u00e7\u00e3o, as estimativas continuarem a estar erradas, analiso os \u00edndices compostos por ordem dos predicados mais seletivos e examino as correla\u00e7\u00f5es entre colunas. O objetivo \u00e9 que, o mais cedo poss\u00edvel, um n\u00famero reduzido de linhas bem pr\u00e9-filtradas seja processado pelos operadores dispendiosos.<\/p>\n\n<h2>Estrat\u00e9gias de semi-join e subconsultas<\/h2>\n\n<p>O MySQL 8 converte frequentemente os predicados IN\/EXISTS em planos de semi-join. No TREE, vejo isso como Materialization, FirstMatch ou Loose Index Scan. Presto aten\u00e7\u00e3o ao seguinte:<\/p>\n<ul>\n  <li><strong>Materializa\u00e7\u00e3o<\/strong>: Um subconjunto \u00e9 criado uma vez e reutilizado v\u00e1rias vezes \u2013 o que \u00e9 adequado para tamanhos moderados.<\/li>\n  <li><strong>FirstMatch<\/strong>: P\u00e1ra logo ap\u00f3s o primeiro acerto \u2013 poupa ciclos quando se prev\u00ea um n\u00famero reduzido de acertos por linha exterior.<\/li>\n  <li><strong>An\u00e1lise de \u00cdndice Livre<\/strong>: Muito eficiente em padr\u00f5es semelhantes ao DISTINCT atrav\u00e9s de \u00edndices.<\/li>\n<\/ul>\n<p>As subconsultas que s\u00e3o executadas por cada linha da tabela externa aumentam excessivamente os \u201eloops\u201c. Transformo-as em JOINs ou materializo-as deliberadamente (CTE\/Derived), para que o plano execute o trabalho dispendioso uma \u00fanica vez e, posteriormente, fa\u00e7a refer\u00eancias de forma mais eficiente.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/08\/mysql_analyze_4892.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Otimiza\u00e7\u00e3o espec\u00edfica de SQL: passo a passo<\/h2>\n\n<p>Come\u00e7o pela estrat\u00e9gia de \u00edndices e otimizo as condi\u00e7\u00f5es WHERE e JOIN mais frequentes com <strong>\u00cdndices<\/strong> . Se precisar de v\u00e1rias colunas no filtro ou na ordena\u00e7\u00e3o, defino \u00edndices compostos e organizo a ordem das colunas de acordo com as mais frequentes <strong>Predicados<\/strong>. Em seguida, otimizo as subconsultas que s\u00e3o executadas em loops, reformulando-as ou convertendo-as em jun\u00e7\u00f5es. Substituo SELECT * por colunas espec\u00edficas, para que sejam movimentados menos dados e o plano seja aliviado. Depois, mantenho as estat\u00edsticas atualizadas, pois estimativas imprecisas levam o otimizador a <strong>Aberra\u00e7\u00f5es<\/strong>.<\/p>\n\n<h2>Pr\u00e1tica de \u00edndices: cobertura, ordem, experi\u00eancias<\/h2>\n\n<p>Utilizo tr\u00eas comandos simples que ficam imediatamente vis\u00edveis no EXPLAIN ANALYZE:<\/p>\n<ul>\n  <li><strong>\u00cdndices de cobertura<\/strong>: Se o \u00edndice incluir todas as colunas necess\u00e1rias (filtro, jun\u00e7\u00e3o, proje\u00e7\u00e3o), o plano evita consultas \u00e0 tabela. O \u201etempo at\u00e9 \u00e0 \u00faltima linha\u201c costuma diminuir significativamente.<\/li>\n  <li><strong>Ordem das colunas<\/strong>: Ordeno por seletividade e tipo de utiliza\u00e7\u00e3o (filtro antes da ordena\u00e7\u00e3o). Para ORDER BY\/GROUP BY, utilizo a dire\u00e7\u00e3o correta e o prefixo adequado.<\/li>\n  <li><strong>Experi\u00eancias com \u00edndices<\/strong>: Com medidas tempor\u00e1rias, <em>invis\u00edveis<\/em> No que diz respeito aos \u00edndices, verifico se o otimizador os escolheria sem desestabilizar os planos existentes. Se o plano melhorar, ativo o \u00edndice de forma permanente.<\/li>\n<\/ul>\n<p>Se existirem v\u00e1rios \u00edndices candidatos, comparo os planos com o EXPLAIN ANALYZE e me\u00e7o sistematicamente o \u201etempo at\u00e9 \u00e0 \u00faltima linha\u201c. Em caso de d\u00favida, o plano escolhido \u00e9 aquele que apresenta o tempo de execu\u00e7\u00e3o mais est\u00e1vel ao longo de diferentes valores dos par\u00e2metros.<\/p>\n\n<h2>Exemplo pr\u00e1tico: analisar o plano, definir o \u00edndice, avaliar o sucesso<\/h2>\n\n<p>Vou abordar uma quest\u00e3o frequente: <code>EXPLAIN ANALYZE SELECT o.id, o.date, c.name FROM orders o JOIN customers c ON c.id = o.customer_id WHERE o.date &gt;= '2025-01-01' ORDER BY o.date DESC;<\/code> e verifica primeiro o n\u00f3 correspondente \u00e0 tabela <strong>encomendas<\/strong>. Se o plano indicar um n\u00famero elevado de linhas reais e uma varredura completa da tabela, crio um \u00edndice adequado, por exemplo, em <code>encomendas(data, id_cliente)<\/code>. Depois, comparo o \u201etime to last row\u201c antes e depois da altera\u00e7\u00e3o, porque este valor ilustra muito claramente o efeito global <strong>espect\u00e1culos<\/strong>. Se a cl\u00e1usula ORDER BY corresponder \u00e0 ordem do \u00edndice, evito ter de ordenar os dados e reduzo significativamente o tempo total. Assim, comprovo os progressos com valores medidos, em vez de com estimativas vagas <strong>Impress\u00f5es<\/strong>.<\/p>\n\n<h2>Analisar instru\u00e7\u00f5es DML de forma segura<\/h2>\n\n<p>No caso de opera\u00e7\u00f5es UPDATE\/DELETE que alteram o conjunto de dados, sigo um procedimento estruturado:<\/p>\n<ul>\n  <li>Encapsulo a medi\u00e7\u00e3o numa transa\u00e7\u00e3o e reverto-a se pretender apenas efetuar a medi\u00e7\u00e3o.<\/li>\n  <li>Estou a verificar se os triggers\/restri\u00e7\u00f5es geram custos adicionais \u2013 o EXPLAIN ANALYZE mostra tempos mais longos nos n\u00f3s afetados.<\/li>\n  <li>Presto aten\u00e7\u00e3o \u00e0 rela\u00e7\u00e3o entre \u201eaffected rows\u201c e \u201erows actual\u201c \u2014 uma rela\u00e7\u00e3o desfavor\u00e1vel indica que a filtragem est\u00e1 a ser feita demasiado tarde ou que faltam \u00edndices.<\/li>\n<\/ul>\n<p>Em instru\u00e7\u00f5es UPDATE que envolvem v\u00e1rias tabelas, a ordem das jun\u00e7\u00f5es e a cobertura do \u00edndice s\u00e3o determinantes. Um \u201etime to last row\u201c prolongado nos n\u00f3s de ordena\u00e7\u00e3o\/jun\u00e7\u00e3o indica a possibilidade de melhorar os \u00edndices ou de reformular a instru\u00e7\u00e3o em duas instru\u00e7\u00f5es espec\u00edficas com armazenamento tempor\u00e1rio.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/08\/mysql_explain_analyze_8374.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Influ\u00eancia do alojamento no desempenho das consultas<\/h2>\n\n<p>N\u00e3o encaro a base de dados de forma isolada, pois a mem\u00f3ria, as E\/S e a CPU influenciam cada <strong>Tempo de execu\u00e7\u00e3o<\/strong>. Os SSDs r\u00e1pidos reduzem o tempo de espera na leitura, uma quantidade suficiente de RAM aumenta o buffer pool e um conjunto de CPUs robusto acelera as opera\u00e7\u00f5es de ordena\u00e7\u00e3o, agrega\u00e7\u00e3o e <strong>Junta-se<\/strong>. Em ambientes de produ\u00e7\u00e3o, prefiro configura\u00e7\u00f5es de alojamento que suportem bem cargas de trabalho com grande volume de dados. Tamb\u00e9m me fornece informa\u00e7\u00f5es \u00fateis sobre temas relacionados com o Optimizer <a href=\"https:\/\/webhosting.de\/pt\/o-otimizador-de-consultas-do-mariadb-explicado-internamente-uma-visao-sobre-o-ajuste-de-sql\/\">Otimizador interno<\/a>, que utilizo como perspetiva complementar. Se combinar um plano bem definido com um ambiente favor\u00e1vel, obtenho ganhos significativos em <strong>Tempos de resposta<\/strong>.<\/p>\n\n<h2>Recursos e operadores no contexto<\/h2>\n\n<p>Ao analisar o plano, presto especial aten\u00e7\u00e3o aos n\u00f3s que consomem muita mem\u00f3ria. As opera\u00e7\u00f5es de ordena\u00e7\u00e3o de grande dimens\u00e3o ou as jun\u00e7\u00f5es hash requerem mem\u00f3ria; se forem demasiado grandes, recorrem a tabelas tempor\u00e1rias. Na \u00e1rvore (TREE), reconhe\u00e7o isso atrav\u00e9s de n\u00f3s tardios e lentos e de uma diferen\u00e7a significativa entre o \u201etempo at\u00e9 \u00e0 primeira linha\u201c e o \u201etempo at\u00e9 \u00e0 \u00faltima linha\u201c. A minha rea\u00e7\u00e3o \u00e9 a seguinte:<\/p>\n<ul>\n  <li>Reduzir o volume de entrada (filtros mais precoces, melhores controladores de jun\u00e7\u00e3o).<\/li>\n  <li>Suporte melhorado ao \u00edndice para a ordem pretendida, de forma a evitar tipos.<\/li>\n  <li>Verificar se o tipo de jun\u00e7\u00e3o (Nested Loop vs. Hash) \u00e9 adequado ao volume de dados.<\/li>\n<\/ul>\n<p>Especialmente nas execu\u00e7\u00f5es de relat\u00f3rios, executo o EXPLAIN ANALYZE em dados representativos, e n\u00e3o em mini-instant\u00e2neos. S\u00f3 assim os valores medidos refletem as cargas reais.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/08\/mysql-analyse-0912.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Boas pr\u00e1ticas para o dia a dia<\/h2>\n\n<p>Primeiro, analiso as consultas que se destacam nos registos ou que os utilizadores referem regularmente como sendo lentas <strong>comunicar<\/strong>. Depois, fa\u00e7o medi\u00e7\u00f5es com o EXPLAIN ANALYZE, registo os n\u00fameros mais importantes e comparo as estimativas com a realidade. Com base nisso, alterei de forma espec\u00edfica os \u00edndices e as formula\u00e7\u00f5es e anotei os resultados \u00abantes\u00bb e \u00abdepois\u00bb, para que o progresso fosse compreens\u00edvel <strong>fazer<\/strong>. Planeio estas an\u00e1lises numa fase inicial do processo de desenvolvimento, em vez de esperar que surjam problemas de produ\u00e7\u00e3o. Atrav\u00e9s de revis\u00f5es repetidas, consigo identificar padr\u00f5es mais rapidamente e tomar decis\u00f5es com maior seguran\u00e7a sobre <strong>Afina\u00e7\u00e3o<\/strong>-medidas.<\/p>\n\n<h2>Lista de verifica\u00e7\u00e3o pragm\u00e1tica para planos mais r\u00e1pidos<\/h2>\n\n<ul>\n  <li>Votos estimados e efetivos <strong>linhas<\/strong> correspondem, em termos gerais? Se n\u00e3o: verificar as estat\u00edsticas\/histogramas.<\/li>\n  <li>Um n\u00f3 domina o \u201etime to last row\u201c? Primeiro candidato a otimiza\u00e7\u00e3o (\u00edndice, escolha de jun\u00e7\u00e3o, evitar ordena\u00e7\u00e3o).<\/li>\n  <li>Os \u201eloops\u201c s\u00e3o muito elevados? Melhorar o driver de jun\u00e7\u00e3o\/\u00edndice na tabela interna ou utilizar uma semi-jun\u00e7\u00e3o.<\/li>\n  <li>Existem ordena\u00e7\u00f5es\/agrupamentos tardios? Alinhar a ordem e a dire\u00e7\u00e3o do \u00edndice com as cl\u00e1usulas ORDER BY\/GROUP BY.<\/li>\n  <li>A consulta precisa mesmo de todas as colunas? Procure criar um \u00edndice de cobertura e simplifique a lista SELECT.<\/li>\n  <li>Subconsulta por linha? Reformular como JOIN ou materializar.<\/li>\n  <li>Est\u00e1vel em rela\u00e7\u00e3o aos par\u00e2metros? Efetue medi\u00e7\u00f5es com v\u00e1rios valores realistas.<\/li>\n<\/ul>\n\n<h2>Erros de interpreta\u00e7\u00e3o comuns e como os evito<\/h2>\n\n<p>N\u00e3o confio cegamente nas estimativas <strong>Custos<\/strong>, se o n\u00famero real de linhas diferir significativamente. Da mesma forma, n\u00e3o tiro conclus\u00f5es precipitadas com base no \u201etime to first row\u201c se o \u201etime to last row\u201c for o fator mais determinante <strong>transporta<\/strong>. Um arranque r\u00e1pido n\u00e3o serve de muito se, no final, a ordena\u00e7\u00e3o ou a jun\u00e7\u00e3o acabarem por dominar. Al\u00e9m disso, analiso minuciosamente os loops, pois estes escondem frequentemente uma jun\u00e7\u00e3o ineficiente ou uma subconsulta que \u00e9 executada por cada linha. S\u00f3 quando o plano, os valores medidos e a distribui\u00e7\u00e3o dos dados estiverem em conson\u00e2ncia \u00e9 que altero <strong>Coisas<\/strong>.<\/p>\n\n<h2>Casos especiais: CTEs, tabelas derivadas, parti\u00e7\u00f5es<\/h2>\n\n<p>As Express\u00f5es de Tabela Comum (CTEs) e as Tabelas Derivadas podem ser materializadas ou fundidas. No TREE, identifico a materializa\u00e7\u00e3o como uma etapa de constru\u00e7\u00e3o separada. Isto \u00e9 vantajoso quando o subfluxo \u00e9 utilizado v\u00e1rias vezes ou se o seu c\u00e1lculo \u00e9 dispendioso. Se as CTEs forem utilizadas apenas uma vez e forem seletivas, uma fus\u00e3o \u00e9 frequentemente mais vantajosa, uma vez que elimina o trabalho adicional de armazenamento. Verifico se o \u201etime to first row\u201c aumenta significativamente \u2013 nesse caso, a materializa\u00e7\u00e3o pode estar sobredimensionada.<\/p>\n<p>As tabelas particionadas s\u00e3o \u00fateis em grandes volumes de dados, desde que o predicado delimite claramente as parti\u00e7\u00f5es. Verifico no plano se a poda (pruning) est\u00e1 a ser aplicada (apenas algumas parti\u00e7\u00f5es s\u00e3o analisadas). Se n\u00e3o for o caso, os custos distribuem-se por todas as parti\u00e7\u00f5es \u2013 um ind\u00edcio de que se deve ajustar as chaves de particionamento aos filtros mais frequentes ou formular a consulta de forma a permitir a poda.<\/p>\n\n<h2>Brevemente resumido<\/h2>\n\n<p>Com o EXPLAIN ANALYZE, consigo quantificar os planos do MySQL e identificar pontos cr\u00edticos, que depois analiso com <strong>\u00cdndices<\/strong>, reformula\u00e7\u00e3o de consultas e estat\u00edsticas atuais. Concentro-me nas discrep\u00e2ncias entre o n\u00famero estimado e o n\u00famero real de linhas, nos tempos at\u00e9 \u00e0 primeira e \u00e0 \u00faltima linha, bem como na <strong>Loops<\/strong>. A partir da\u00ed, deduzo algumas etapas eficazes e volto a verificar cada efeito com o comando EXPLAIN ANALYZE. Com o tempo, consigo identificar padr\u00f5es imediatamente e implementar as medidas adequadas mais rapidamente. \u00c9 assim que aumento a <strong>Desempenho<\/strong> s\u00e3o fi\u00e1veis e mant\u00eam as consultas est\u00e1veis a longo prazo.<\/p>","protected":false},"excerpt":{"rendered":"<p>Aprenda a utilizar o MySQL EXPLAIN ANALYZE para compreender os planos de execu\u00e7\u00e3o e otimizar de forma espec\u00edfica as suas consultas SQL com a palavra-chave \u00abmysql explain analyze\u00bb.<\/p>","protected":false},"author":1,"featured_media":21003,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[781],"tags":[],"class_list":["post-21010","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-datenbanken-administration-anleitungen"],"acf":[],"_wp_attached_file":null,"_wp_attachment_metadata":null,"litespeed-optimize-size":null,"litespeed-optimize-set":null,"_elementor_source_image_hash":null,"_wp_attachment_image_alt":null,"stockpack_author_name":null,"stockpack_author_url":null,"stockpack_provider":null,"stockpack_image_url":null,"stockpack_license":null,"stockpack_license_url":null,"stockpack_modification":null,"color":null,"original_id":null,"original_url":null,"original_link":null,"unsplash_location":null,"unsplash_sponsor":null,"unsplash_exif":null,"unsplash_attachment_metadata":null,"_elementor_is_screenshot":null,"surfer_file_name":null,"surfer_file_original_url":null,"envato_tk_source_kit":null,"envato_tk_source_index":null,"envato_tk_manifest":null,"envato_tk_folder_name":null,"envato_tk_builder":null,"envato_elements_download_event":null,"_menu_item_type":null,"_menu_item_menu_item_parent":null,"_menu_item_object_id":null,"_menu_item_object":null,"_menu_item_target":null,"_menu_item_classes":null,"_menu_item_xfn":null,"_menu_item_url":null,"_trp_menu_languages":null,"rank_math_primary_category":null,"rank_math_title":null,"inline_featured_image":null,"_yoast_wpseo_primary_category":null,"rank_math_schema_blogposting":null,"rank_math_schema_videoobject":null,"_oembed_049c719bc4a9f89deaead66a7da9fddc":null,"_oembed_time_049c719bc4a9f89deaead66a7da9fddc":null,"_yoast_wpseo_focuskw":null,"_yoast_wpseo_linkdex":null,"_oembed_27e3473bf8bec795fbeb3a9d38489348":null,"_oembed_c3b0f6959478faf92a1f343d8f96b19e":null,"_trp_translated_slug_en_us":null,"_wp_desired_post_slug":null,"_yoast_wpseo_title":null,"tldname":null,"tldpreis":null,"tldrubrik":null,"tldpolicylink":null,"tldsize":null,"tldregistrierungsdauer":null,"tldtransfer":null,"tldwhoisprivacy":null,"tldregistrarchange":null,"tldregistrantchange":null,"tldwhoisupdate":null,"tldnameserverupdate":null,"tlddeletesofort":null,"tlddeleteexpire":null,"tldumlaute":null,"tldrestore":null,"tldsubcategory":null,"tldbildname":null,"tldbildurl":null,"tldclean":null,"tldcategory":null,"tldpolicy":null,"tldbesonderheiten":null,"tld_bedeutung":null,"_oembed_d167040d816d8f94c072940c8009f5f8":null,"_oembed_b0a0fa59ef14f8870da2c63f2027d064":null,"_oembed_4792fa4dfb2a8f09ab950a73b7f313ba":null,"_oembed_33ceb1fe54a8ab775d9410abf699878d":null,"_oembed_fd7014d14d919b45ec004937c0db9335":null,"_oembed_21a029d076783ec3e8042698c351bd7e":null,"_oembed_be5ea8a0c7b18e658f08cc571a909452":null,"_oembed_a9ca7a298b19f9b48ec5914e010294d2":null,"_oembed_f8db6b27d08a2bb1f920e7647808899a":null,"_oembed_168ebde5096e77d8a89326519af9e022":null,"_oembed_cdb76f1b345b42743edfe25481b6f98f":null,"_oembed_87b0613611ae54e86e8864265404b0a1":null,"_oembed_27aa0e5cf3f1bb4bc416a4641a5ac273":null,"_oembed_time_27aa0e5cf3f1bb4bc416a4641a5ac273":null,"_tldname":null,"_tldclean":null,"_tldpreis":null,"_tldcategory":null,"_tldsubcategory":null,"_tldpolicy":null,"_tldpolicylink":null,"_tldsize":null,"_tldregistrierungsdauer":null,"_tldtransfer":null,"_tldwhoisprivacy":null,"_tldregistrarchange":null,"_tldregistrantchange":null,"_tldwhoisupdate":null,"_tldnameserverupdate":null,"_tlddeletesofort":null,"_tlddeleteexpire":null,"_tldumlaute":null,"_tldrestore":null,"_tldbildname":null,"_tldbildurl":null,"_tld_bedeutung":null,"_tldbesonderheiten":null,"_oembed_ad96e4112edb9f8ffa35731d4098bc6b":null,"_oembed_8357e2b8a2575c74ed5978f262a10126":null,"_oembed_3d5fea5103dd0d22ec5d6a33eff7f863":null,"_eael_widget_elements":null,"_oembed_0d8a206f09633e3d62b95a15a4dd0487":null,"_oembed_time_0d8a206f09633e3d62b95a15a4dd0487":null,"_aioseo_description":null,"_eb_attr":null,"_eb_data_table":null,"_oembed_819a879e7da16dd629cfd15a97334c8a":null,"_oembed_time_819a879e7da16dd629cfd15a97334c8a":null,"_acf_changed":null,"_wpcode_auto_insert":null,"_edit_last":null,"_edit_lock":null,"_oembed_e7b913c6c84084ed9702cb4feb012ddd":null,"_oembed_bfde9e10f59a17b85fc8917fa7edf782":null,"_oembed_time_bfde9e10f59a17b85fc8917fa7edf782":null,"_oembed_03514b67990db061d7c4672de26dc514":null,"_oembed_time_03514b67990db061d7c4672de26dc514":null,"rank_math_news_sitemap_robots":null,"rank_math_robots":null,"_eael_post_view_count":"121","_trp_automatically_translated_slug_ru_ru":null,"_trp_automatically_translated_slug_et":null,"_trp_automatically_translated_slug_lv":null,"_trp_automatically_translated_slug_fr_fr":null,"_trp_automatically_translated_slug_en_us":null,"_wp_old_slug":null,"_trp_automatically_translated_slug_da_dk":null,"_trp_automatically_translated_slug_pl_pl":null,"_trp_automatically_translated_slug_es_es":null,"_trp_automatically_translated_slug_hu_hu":null,"_trp_automatically_translated_slug_fi":null,"_trp_automatically_translated_slug_ja":null,"_trp_automatically_translated_slug_lt_lt":null,"_elementor_edit_mode":null,"_elementor_template_type":null,"_elementor_version":null,"_elementor_pro_version":null,"_wp_page_template":null,"_elementor_page_settings":null,"_elementor_data":null,"_elementor_css":null,"_elementor_conditions":null,"_happyaddons_elements_cache":null,"_oembed_75446120c39305f0da0ccd147f6de9cb":null,"_oembed_time_75446120c39305f0da0ccd147f6de9cb":null,"_oembed_3efb2c3e76a18143e7207993a2a6939a":null,"_oembed_time_3efb2c3e76a18143e7207993a2a6939a":null,"_oembed_59808117857ddf57e478a31d79f76e4d":null,"_oembed_time_59808117857ddf57e478a31d79f76e4d":null,"_oembed_965c5b49aa8d22ce37dfb3bde0268600":null,"_oembed_time_965c5b49aa8d22ce37dfb3bde0268600":null,"_oembed_81002f7ee3604f645db4ebcfd1912acf":null,"_oembed_time_81002f7ee3604f645db4ebcfd1912acf":null,"_elementor_screenshot":null,"_oembed_7ea3429961cf98fa85da9747683af827":null,"_oembed_time_7ea3429961cf98fa85da9747683af827":null,"_elementor_controls_usage":null,"_elementor_page_assets":[],"_elementor_screenshot_failed":null,"theplus_transient_widgets":null,"_eael_custom_js":null,"_wp_old_date":null,"_trp_automatically_translated_slug_it_it":null,"_trp_automatically_translated_slug_pt_pt":null,"_trp_automatically_translated_slug_zh_cn":null,"_trp_automatically_translated_slug_nl_nl":null,"_trp_automatically_translated_slug_pt_br":null,"_trp_automatically_translated_slug_sv_se":null,"rank_math_analytic_object_id":null,"rank_math_internal_links_processed":"1","_trp_automatically_translated_slug_ro_ro":null,"_trp_automatically_translated_slug_sk_sk":null,"_trp_automatically_translated_slug_bg_bg":null,"_trp_automatically_translated_slug_sl_si":null,"litespeed_vpi_list":null,"litespeed_vpi_list_mobile":null,"rank_math_seo_score":null,"rank_math_contentai_score":null,"ilj_limitincominglinks":null,"ilj_maxincominglinks":null,"ilj_limitoutgoinglinks":null,"ilj_maxoutgoinglinks":null,"ilj_limitlinksperparagraph":null,"ilj_linksperparagraph":null,"ilj_blacklistdefinition":null,"ilj_linkdefinition":null,"_eb_reusable_block_ids":null,"rank_math_focus_keyword":"mysql explain","rank_math_og_content_image":null,"_yoast_wpseo_metadesc":null,"_yoast_wpseo_content_score":null,"_yoast_wpseo_focuskeywords":null,"_yoast_wpseo_keywordsynonyms":null,"_yoast_wpseo_estimated-reading-time-minutes":null,"rank_math_description":null,"surfer_last_post_update":null,"surfer_last_post_update_direction":null,"surfer_keywords":null,"surfer_location":null,"surfer_draft_id":null,"surfer_permalink_hash":null,"surfer_scrape_ready":null,"_thumbnail_id":"21003","footnotes":null,"_links":{"self":[{"href":"https:\/\/webhosting.de\/pt\/wp-json\/wp\/v2\/posts\/21010","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/webhosting.de\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/webhosting.de\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/webhosting.de\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/webhosting.de\/pt\/wp-json\/wp\/v2\/comments?post=21010"}],"version-history":[{"count":0,"href":"https:\/\/webhosting.de\/pt\/wp-json\/wp\/v2\/posts\/21010\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/webhosting.de\/pt\/wp-json\/wp\/v2\/media\/21003"}],"wp:attachment":[{"href":"https:\/\/webhosting.de\/pt\/wp-json\/wp\/v2\/media?parent=21010"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/webhosting.de\/pt\/wp-json\/wp\/v2\/categories?post=21010"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/webhosting.de\/pt\/wp-json\/wp\/v2\/tags?post=21010"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}