EXPLAIN nome_tabela ou EXPLAIN SELECT opções_select
        EXPLAIN nome_tabela é um sinônimo para
        DESCRIBE nome_tabela ou SHOW COLUMNS
        FROM nome_tabela.
      
        Quando uma instrução SELECT for precedida
        da palavra chave EXPLAIN, o MySQL explicará
        como ele deve processar a SELECT, fornecendo
        informação sobre como as tabelas estão sendo unidas e em qual
        ordem.
      
        Com a ajuda de EXPLAIN, você pode ver quando
        devem ser adicionados índices à tabelas para obter uma
        SELECT mais rápida que utiliza índices para
        encontrar os registros.
      
        Voce deve executar frequentemente ANALYZE
        TABLE para atualizar estatísticas de tabela tais como
        a cardinalidade das chaves que podem afetar a escolha que o
        otimizador faz. See Secção 4.6.2, “Sintaxe de ANALYZE TABLE”.
      
        Você também pode ver se o otimizador une as tabelas em uma
        melhor ordem. Para forçar o otimizador a utilizar uma ordem
        específica de join para uma instrução
        SELECT, adicione uma cláusula
        STRAIGHT_JOIN.
      
        Para ligações mais complexas, EXPLAIN
        retorna uma linha de informação para cada tabela utilizada na
        instrução SELECT. As tabelas são listadas
        na ordem que seriam lidas. O MySQL soluciona todas as joins
        utilizando um método multi-join de varedura simples. Isto
        significa que o MySQL lê uma linha da primeira tabela, depois
        encontra uma linha que combina na segunda tabela, depois na
        terceira tabela e continua. Quando todas tabelas são
        processadas, ele exibe as colunas selecionadas e recua através
        da lista de tabelas até uma tabela na qual existem registros
        coincidentes for encontrada. O próximo registro é lido desta
        tabela e o processo continua com a próxima tabela.
      
        No MySQL versão 4.1 a saída do EXPLAIN foi
        alterada para funcionar melhor com construções como
        UNIONs, subqueries e tabelas derivadas. A
        mais notável é a adição de duas novas colunas:
        id e select_type.
      
        A saída de EXPLAIN inclui as seguintes
        colunas:
      
            id
          
            Identificador SELECT, o número
            sequêncial desta SELECT dentro da
            consulta.
          
            select_type
          
            Tipo de cláusula SELECT, que pode ser
            uma das seguintes:
          
                SIMPLE
              
                SELECT simples (sem
                UNIONs ou subqueries).
              
                PRIMARY
              
                SELECT mais externa.
              
                UNION
              
                Segunda SELECT e as
                SELECTs posteriores do
                UNION
              
                DEPENDENT UNION
              
                Seunda SELECT e
                SELECTs posteriores do
                UNION, dependente da subquery
                exterior.
              
                SUBQUERY
              
                Primeiro SELECT na subquery.
              
                DEPENDENT SUBQUERY
              
                Primeiro SELECT, dependente da
                subquery exterior.
              
                DERIVED
              
                SELECT de tabela derivada (subquery
                na cláusula FROM).
              
            table
          
A tabela para a qual a linha de saída se refere.
            type
          
O tipo de join. Os diferentes tipos de joins são listados aqui, ordenados do melhor para o pior tipo:
                system
              
                A tabela só tem uma linha (= tabela de sistema). Este
                é um caso especial do tipo de join
                const.
              
                const
              
                A tabela têm no máximo um registro coincidente, o qual
                será lido na inicialização da consulta. Como só há
                um registro, os valores da coluna neste registro podem
                ser considerados constantes pelo resto do otimizador.
                Tabelas const são muito rápidas e
                são lidas apenas uma vez!
              
                const é usado quando você compara
                todas as partes de uma chave
                PRIMARY/UNIQUE com
                restrições:
              
SELECT * FROM const_table WHERE primary_key=1; SELECT * FROM const_table WHERE primary_key_part1=1 AND primary_key_part2=2;
                eq_ref
              
                Uma linha será lida desta tabela para cada combinação
                de linhas da tabela anterior. Este é o melhor tipo de
                join depois dos tipos const. É usado
                quando todas as partes do índice são usados pela join
                e o índice é é único (UNIQUE) ou
                uma chave primária (PRIMARY KEY).
              
                eq_ref pode ser usado para coluna
                indexadas que é comparada com o\ operador
                =. O item comparado pode ser uma
                constante ou uma expressão que usa colunas de tabelas
                que são lidas antes desta tabela.
              
                Nos seguintes examplos, ref_table
                poderá usar eq_ref
              
SELECT * FROM ref_table,other_table WHERE ref_table.key_column=other_table.column; SELECT * FROM ref_table,other_table WHERE ref_table.key_column_part1=other_table.column AND ref_table.key_column_part2=1;
                ref
              
                Todas as colunas com valores de índices correspondentes
                serão lidos desta tabela para cada combinação de
                registros da tabela anterior. ref é
                usado se o join usa apenas o prefixo mais a esquerda da
                chave, ou se a chave não é única
                (UNIQUE) ou uma chave primária
                (PRIMARY KEY) (em outras palavras, se
                a join não puder selecionar um único registro baseado
                no valor da chave). Se a chave que é usada coincide
                apenas em alguns registros, este tipo de join é bom.
              
                ref pode ser usado para colunas
                indexadas que são comparadas com o operador
                =.
              
                Nos seguintes exemplos, ref_table
                poderá usar ref
              
SELECT * FROM ref_table WHERE key_column=expr; SELECT * FROM ref_table,other_table WHERE ref_table.key_column=other_table.column; SELECT * FROM ref_table,other_table WHERE ref_table.key_column_part1=other_table.column AND ref_table.key_column_part2=1;
                ref_or_null
              
                Como ref, mas com o adicional que
                faremos uma busca extra para linhas com
                NULL. See
                Secção 5.2.5, “Como o MySQL Otimiza IS NULL”.
              
SELECT * FROM ref_table WHERE key_column=expr OR key_column IS NULL;
Esta otimização do tipo join é nova para o MySQL 4.1.1 e é mais usada na resolução de sub queries.
                range
              
                Apenas registros que estão numa dada faixa serão
                retornados, usando um índice para selecionar os
                registros. A coluna key indica qual
                índice é usado. key_len contém a
                maior parte da chave que foi usada. A coluna
                ref será NULL
                para este tipo.
              
                range pode ser usado para quando uma
                coluna de chave é comparada a uma constante com
                =, <>,
                >, >=,
                <, <=,
                IS NULL,
                <=>, BETWEEN
                e IN.
              
SELECT * FROM range_table WHERE key_column = 10; SELECT * FROM range_table WHERE key_column BETWEEN 10 and 20; SELECT * FROM range_table WHERE key_column IN (10,20,30); SELECT * FROM range_table WHERE key_part1= 10 and key_part2 IN (10,20,30);
                index
              
                Isto é o mesmo que ALL, exceto que
                apenas a árvore de índice é varrida. Isto é
                normalmente mais rápido que ALL, já
                que o arquivo de índice normalmente é menor que o
                arquivo de dados.
              
Ele pode ser usado quando a consulta só usa colunas que são parte de um índice.
                ALL
              
                Será feita uma varredura completa da tabela para cada
                combinação de registros da tabela anterior. Isto
                normalmente não é bom se a tabela é a primeiro tabela
                não marcada como const, e
                normalmente muito ruim
                em todos os casos ordenados. Você normalmente pode
                ebitar ALL adicionando mais índices,
                assim o registro pode ser retornado baseado em valores
                constantes ou valores de colunas de tabelas anteriores.
              
            possible_keys
          
            A coluna possible_keys indica quais
            índices o MySQL pode utilizar para encontrar os registros
            nesta tabela. Note que esta coluna é totalmente
            independente da ordem das tabelas. Isto significa que
            algumas das chaves em possible_keys podem
            não ser usadas na prática com a ordem de tabela gerada.
          
            Se esta coluna for NULL, não existem
            índices relevantes. Neste caso, você poderá melhora a
            performance de sua query examinando a cláusula
            WHERE para ver se ela refere a alguma
            coluna ou colunas que podem ser indexadas. Se for verdade,
            crie um índice apropriado e confira a consulta com
            EXPLAIN novamente. See
            Secção 6.5.4, “Sintaxe ALTER TABLE”.
          
            Para ver os índices existentes em uma tabela, utilize
            SHOW INDEX FROM nome_tabela.
          
            key
          
            A coluna key indica a chave (índice) que
            o MySQL decidiu usar. A chave será NULL
            se nenhum índice for escolhido. Para forçar o MySQL a usar
            um índice listado na coluna
            possible_keys, use USE
            INDEX/IGNORE INDEX em sua consulta. See
            Secção 6.4.1, “Sintaxe SELECT”.
          
            Executando myisamchk --analyze (see
            Secção 4.5.6.1, “Sintaxe do myisamchk”) ou ANALYSE
            TABLE (see Secção 4.6.2, “Sintaxe de ANALYZE TABLE”) na
            tabela também ajudará o otimizador a escolher índices
            melhores.
          
            key_len
          
            A coluna key_len indica o tamanho da
            chave que o MySQL decidiu utilizar. O tamanho será
            NULL se key for
            NULL. Note que isto nos diz quantas
            partes de uma chave multi-partes o MySQL realmente está
            utilizando.
          
            ref
          
            A coluna ref exibe quais colunas ou
            contantes são usadas com a key para
            selecionar registros da tabela.
          
            rows
          
            A coluna rows informa o número de linhas
            que o MySQL deve examinar para executar a consulta.
          
            Extra
          
Esta coluna contem informações adicionais de como o MySQL irá resolver a consulta. A seguir uma explicação das diferentes strings de texto que podem ser encontradas nesta coluna:
                Distinct
              
O MySQL não continuará a procurar por mais registros para a combinação de registro atual depois de ter encontrado o primeiro registro coincidente.
                Not exists
              
                O MySQL estava apto a fazer uma otimização
                LEFT JOIN na consulta e não
                examinará mais registros nesta tabela para a
                combinação do registro anterior depois que encontrar
                um registro que satisfaça o critério do LEFT
                JOIN.
              
Exemplo:
SELECT * FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL;
                Assume que t2.id é definido com
                NOT NULL. Neste caso o MySQL irá
                percorrer t1 e procurar pelos
                registros em t2 através de
                t1.id. Se o MySQL encontrar um
                registro combinando em t2, ele sabe
                que t2.id nunca poderá ser
                NULL e não ir percorrer até o resto
                dos registros em t2 que possuirem o
                mesmo id. Em outras palavras, para
                cada registro em t1 o MySQL só
                precisa fazer uma única pesquisa em
                t2, independente de quantos registros
                coincidentes existirem em t2.
              
                range checked for each record (index map:
                #)
              
O MySQL não encontrou um bom índice para usar. No lugar, ele irá fazer uma verificação sobre qual índice usar (se existir) para cada combinação das tabelas precedentes, e usará este índice para recuperar os registros da tabela. Isto não é muito rápido mas é mais rápido que fazer um join sem um índice.
                Using filesort
              
                O MySQL precisará fazer uma passada extra para
                descobrir como recuperar os registros na ordem de
                classificação. A classificação é feita indo
                através de todos os registros de acordo com
                join type e armazenar a chave de
                ordenação mais o ponteiro para o registro para todos
                os registros que combinarem com o
                WHERE. Então as chaves são
                classificadas. Finalmente os registros são recuperados
                na ordem de classificação.
              
                Using index
              
A informação da coluna é recuperada da tabela utilizando somente informações na árvore de índices sem ter que fazer uma pesquisa adicional para ler o registro atual. Isto pode ser feito quando todas as colunas usadas para a tabela fizerem parte do mesmo índice.
                Using temporary
              
                Para resolver a consulta, o MySQL precisará criar uma
                tabela temporária para armazenar o resultado. Isto
                acontece normalmente se você fizer um ORDER
                BY em um conjunto de colunas diferentes das
                quais você fez um GROUP BY.
              
                Using where
              
                Uma cláusula WHERE será utilizada
                para restringir quais registros serão combinados com a
                próxima tabela ou enviar para o cliente. se você não
                possui esta informação e a tabela é do tipo
                ALL ou index, pode
                existir alguma coisa errada na sua query (Se você não
                pretender examinar todos os registros da tabela).
              
            Se você desejar deixar suas consultas o mais rápido
            possível, você deve dar uma olhada em Using
            filesort e Using temporary.
          
        Você pode ter uma boa indicação de quão boa é sua join
        multiplicando todos os valores na coluna rows
        na saída de EXPLAIN. Isto deve dizer a
        grosso modo quantos registros o MySQL deve examinar para
        executar a consulta. Este número é também usado quando você
        restringe consultas com a variável
        max_join_size. See
        Secção 5.5.2, “Parâmetros de Sintonia do Servidor”.
      
        O exemplo a seguir mostra como um JOIN pode
        ser otimizado progressivamente utilizando a informação
        fornecida por EXPLAIN.
      
        Suponha que você tem a instrução SELECT
        exibida abaixo, que você está examinando utilizando
        EXPLAIN:
      
EXPLAIN SELECT tt.TicketNumber, tt.TimeIn,
            tt.ProjectReference, tt.EstimatedShipDate,
            tt.ActualShipDate, tt.ClientID,
            tt.ServiceCodes, tt.RepetitiveID,
            tt.CurrentProcess, tt.CurrentDPPerson,
            tt.RecordVolume, tt.DPPrinted, et.COUNTRY,
            et_1.COUNTRY, do.CUSTNAME
        FROM tt, et, et AS et_1, do
        WHERE tt.SubmitTime IS NULL
            AND tt.ActualPC = et.EMPLOYID
            AND tt.AssignedPC = et_1.EMPLOYID
            AND tt.ClientID = do.CUSTNMBR;
Para este exemplo, assuma que:
As colunas comparadas foram declaradas como a seguir:
| Tabela | Coluna | Tipo da coluna | 
| tt | ActualPC | CHAR(10) | 
| tt | AssignedPC | CHAR(10) | 
| tt | ClientID | CHAR(10) | 
| et | EMPLOYID | CHAR(15) | 
| do | CUSTNMBR | CHAR(15) | 
As tabelas possuem os índices mostrados abaixo:
| Tabela | Índice | 
| tt | ActualPC | 
| tt | AssignedPC | 
| tt | ClientID | 
| et | EMPLOYID(chave primária) | 
| do | CUSTNMBR(chave primária) | 
            The tt.ActualPC values aren't evenly
            distributed.
          
        Initially, before any optimizations have been performed, the
        EXPLAIN statement produces the following
        information:
      
table type possible_keys                key  key_len ref  rows  Extra
et    ALL  PRIMARY                      NULL NULL    NULL 74
do    ALL  PRIMARY                      NULL NULL    NULL 2135
et_1  ALL  PRIMARY                      NULL NULL    NULL 74
tt    ALL  AssignedPC,ClientID,ActualPC NULL NULL    NULL 3872
      range checked for each record (key map: 35)
        Como o tipo é ALL em
        todas tabelas, esta saída indica que o MySQL está gerando um
        produto Cartesiano de todas as tabelas! Isto levará muito tempo
        para ser executado, pois o produto do número de registros em
        cada tabela deve ser examinado ! Neste caso, existem 74
        * 2135 * 74 * 3872 registros. Se as tabelas forem
        maiores, imagine quanto tempo este tipo de consulta pode
        demorar.
      
        Um dos problemas aqui é que o MySQL não pode (ainda) utilizar
        índices em colunas de maneira eficiente se elas foram declaras
        ide forma diferente. Neste contexto, VARCHAR
        e CHAR são o mesmo a menos que tenham sido
        declarados com tamanhos diferentes. Como
        tt.ActualPC é declarado como
        CHAR(10) e et.EMPLOYID é
        declarado como CHAR(15), existe aqui uma
        diferença de tamanho.
      
        Para corrigir esta diferença entre tamanhos de registros,
        utilize ALTER TABLE para alterar o tamanho de
        ActualPC de 10 para 15 caracteres:
      
mysql> ALTER TABLE tt MODIFY ActualPC VARCHAR(15);
        Agora ambos campos tt.ActualPC e
        et.EMPLOYID são
        VARCHAR(15). Executando a instrução
        EXPLAIN novamente produzirá este resultado:
      
table type   possible_keys   key     key_len ref         rows    Extra
tt    ALL    AssignedPC,ClientID,ActualPC NULL NULL NULL 3872    Using where
do    ALL    PRIMARY         NULL    NULL    NULL        2135
      range checked for each record (key map: 1)
et_1  ALL    PRIMARY         NULL    NULL    NULL        74
      range checked for each record (key map: 1)
et    eq_ref PRIMARY         PRIMARY 15      tt.ActualPC 1
        Isto não está perfeito, mas está bem melhor ( o produto dos
        valores de rows agora menor por um fator de
        74 ). Esta versão é executada em vários segundos.
      
        Uma segunda alteração pode ser feita para eliminar as
        diferenças de tamanho das colunas para as comparações
        tt.AssignedPC = et_1.EMPLOYID e
        tt.ClientID = do.CUSTNMBR :
      
mysql>ALTER TABLE tt MODIFY AssignedPC VARCHAR(15),->MODIFY ClientID VARCHAR(15);
        Agora EXPLAIN produz a saída mostrada
        abaixo:
      
table type   possible_keys   key      key_len ref           rows Extra
et    ALL    PRIMARY         NULL     NULL    NULL          74
tt    ref    AssignedPC,     ActualPC 15      et.EMPLOYID   52   Using where
             ClientID,
             ActualPC
et_1  eq_ref PRIMARY         PRIMARY  15      tt.AssignedPC 1
do    eq_ref PRIMARY         PRIMARY  15      tt.ClientID   1
Este resultado é quase o melhor que se pode obter.
        O problema restante é que, por padrão, o MySQL assume que
        valores na coluna tt.ActualPC estão
        distribuídos igualmente, e este não é o caso para a tabela
        tt. Felizmente, é fácil informar ao MySQL
        sobre isto:
      
shell>myisamchk --analyze PATH_TO_MYSQL_DATABASE/ttshell>mysqladmin refresh
        Agora a join está perfeita, e EXPLAIN produz
        esta saída:
      
table type   possible_keys key     key_len ref           rows Extra
tt    ALL    AssignedPC    NULL    NULL    NULL          3872 Using where
             ClientID,
             ActualPC
et    eq_ref PRIMARY       PRIMARY 15      tt.ActualPC   1
et_1  eq_ref PRIMARY       PRIMARY 15      tt.AssignedPC 1
do    eq_ref PRIMARY       PRIMARY 15      tt.ClientID   1
        Perceba que a coluna rows na saída de
        EXPLAIN é uma boa ajuda para otimizador de
        joins do MySQL. Para otimizar uma consulta, você deve conferir
        se os números estão perto da realidade. Se não, você pode
        obter melhor desempenho utilizando
        STRAIGHT_JOIN em sua instrução
        SELECT e tentar listar as tabelas em uma
        ordem diferente na cláusula FROM.
      
This is a translation of the MySQL Reference Manual that can be found at dev.mysql.com. The original Reference Manual is in English, and this translation is not necessarily as up to date as the English version.

