O MySQL visualizar sempre fazer varredura completa da tabela?
-
10-07-2019 - |
Pergunta
Eu estou tentando otimizar uma consulta que utiliza uma vista no MySQL 5.1. Parece que mesmo se eu selecionar uma coluna da vista sempre faz uma varredura completa da tabela. É que o comportamento esperado?
A vista é apenas um SELECT "todas as colunas destas tabelas - NÃO *". Para as tabelas I especificou na primeira consulta abaixo
Este é o meu explicar a saída de quando eu selecionar o PromotionID coluna indexada a partir da consulta que compõe a vista. Como você pode ver que é muito diferente do de saída no ponto de vista.
EXPLAIN SELECT pb.PromotionID FROM PromotionBase pb INNER JOIN PromotionCart pct ON pb.PromotionID = pct.PromotionID INNER JOIN PromotionCode pc ON pb.PromotionID = pc.PromotionID WHERE pc.PromotionCode = '5TAFF312C0NT'\G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: pc
type: const
possible_keys: PRIMARY,fk_pc_pb
key: PRIMARY
key_len: 302
ref: const
rows: 1
Extra:
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: pb
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 1
Extra: Using index
*************************** 3. row ***************************
id: 1
select_type: SIMPLE
table: pct
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 1
Extra: Using index
3 rows in set (0.00 sec)
A saída quando eu selecionar a mesma coisa, mas do ponto de vista ??p>
EXPLAIN SELECT vpc.PromotionID FROM vw_PromotionCode vpc WHERE vpc.PromotionCode = '5TAFF312C0NT'\G;
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: <derived2>
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 5830
Extra: Using where
*************************** 2. row ***************************
id: 2
select_type: DERIVED
table: pcart
type: index
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: NULL
rows: 33
Extra: Using index
*************************** 3. row ***************************
id: 2
select_type: DERIVED
table: pb
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: readyinteractive.pcart.PromotionID
rows: 1
Extra:
*************************** 4. row ***************************
id: 2
select_type: DERIVED
table: pc
type: ref
possible_keys: fk_pc_pb
key: fk_pc_pb
key_len: 4
ref: readyinteractive.pb.PromotionID
rows: 249
Extra: Using where
*************************** 5. row ***************************
id: 3
select_type: UNION
table: pp
type: index
possible_keys: PRIMARY
key: pp_p
key_len: 4
ref: NULL
rows: 1
Extra: Using index
*************************** 6. row ***************************
id: 3
select_type: UNION
table: pb
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: readyinteractive.pp.PromotionID
rows: 1
Extra:
*************************** 7. row ***************************
id: 3
select_type: UNION
table: pc
type: ref
possible_keys: fk_pc_pb
key: fk_pc_pb
key_len: 4
ref: readyinteractive.pb.PromotionID
rows: 249
Extra: Using where
*************************** 8. row ***************************
id: 4
select_type: UNION
table: pcp
type: index
possible_keys: PRIMARY
key: pcp_cp
key_len: 4
ref: NULL
rows: 1
Extra: Using index
*************************** 9. row ***************************
id: 4
select_type: UNION
table: pb
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: readyinteractive.pcp.PromotionID
rows: 1
Extra:
*************************** 10. row ***************************
id: 4
select_type: UNION
table: pc
type: ref
possible_keys: fk_pc_pb
key: fk_pc_pb
key_len: 4
ref: readyinteractive.pb.PromotionID
rows: 249
Extra: Using where
*************************** 11. row ***************************
id: 5
select_type: UNION
table: ppc
type: index
possible_keys: PRIMARY
key: ppc_pc
key_len: 4
ref: NULL
rows: 1
Extra: Using index
*************************** 12. row ***************************
id: 5
select_type: UNION
table: pb
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: readyinteractive.ppc.PromotionID
rows: 1
Extra:
*************************** 13. row ***************************
id: 5
select_type: UNION
table: pc
type: ref
possible_keys: fk_pc_pb
key: fk_pc_pb
key_len: 4
ref: readyinteractive.pb.PromotionID
rows: 249
Extra: Using where
*************************** 14. row ***************************
id: 6
select_type: UNION
table: ppt
type: index
possible_keys: PRIMARY
key: ppt_pt
key_len: 4
ref: NULL
rows: 1
Extra: Using index
*************************** 15. row ***************************
id: 6
select_type: UNION
table: pb
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: readyinteractive.ppt.PromotionID
rows: 1
Extra:
*************************** 16. row ***************************
id: 6
select_type: UNION
table: pc
type: ref
possible_keys: fk_pc_pb
key: fk_pc_pb
key_len: 4
ref: readyinteractive.pb.PromotionID
rows: 249
Extra: Using where
*************************** 17. row ***************************
id: NULL
select_type: UNION RESULT
table: <union2,3,4,5,6>
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: NULL
Extra:
17 rows in set (0.18 sec)
Solução
Visualizações em MySQL não são indexadas por isso pela sua própria natureza requerem uma verificação completa cada vez que eles são acessados. Em geral, isso faz Visualizações realmente útil apenas para situações onde você tem uma consulta estática bastante complexo que retorna um pequeno conjunto de resultados e você planeja pegar todo o resultado de cada vez.
Editar: É claro Visualizações usará os índices nas tabelas subjacentes para que a vista em si é otimizado (caso contrário, não faria qualquer sentido para uso), mas porque não existem índices em uma exibição que não é possível para um WHERE consulta a exibição de ser otimizado.
A construção de índices para Visualizações seria caro de qualquer maneira porque enquanto eu não tentei ao perfil quaisquer pontos de vista, estou bastante certo de que uma tabela temporária é construída nos bastidores e, em seguida, o conjunto de resultados retornado. Já leva muito tempo para construir a tabela temporária, eu não iria querer uma visão que também tenta adivinhar o que os índices são necessários. Que traz o segundo ponto que é que o MySQL atualmente não oferecem um método para especificar quais índices usar para uma exibição de modo como ele sabe quais campos precisam ser indexados? Será que adivinhar com base na sua consulta?
Você pode considerar usando um href="http://dev.mysql.com/doc/refman/5.1/en/create-table.html" rel="noreferrer"> temporária Tabela
Se tudo isso exibição contém é um SELECT ALL FROM tabela1, tabela2, table3; então eu teria que perguntar por que esta consulta precisa estar em uma exibição em tudo? Se por algum motivo a sua absolutamente necessário, você pode querer usar um procedimento armazenado para encapsular a consulta como então você vai ser capaz de obter um desempenho otimizado, mantendo o benefício de uma chamada simples para o banco de dados para o conjunto de resultados.
Outras dicas
Eu olhei mais profundo em que um eu perdi um ponto-chave de informações :( Meu consulta vista realmente tem uma união com outra mesa. Isso está causando a fim de usar o algoritmo TEMPORARY TABLE em vez do algoritmo MERGE.
O algoritmo TEMPORARY TABLE não permite o uso de índices nas tabelas subjacentes.
Este parece ser um bug no MySQL e foi relatado caminho de volta em 2006, mas não parece ter sido resolvido em 2009! http://forums.mysql.com/read.php?100,56681, 56681
Parece que eu só vou ter que re-escrever a consulta como uma junção externa.