Concordo com todos os pontos da excelente resposta de Bill Karwin.
P: É uma prática normal criar uma visão para consulta de união discutida e usá-la em minhas junções, subseleções etc?
R: Com o MySQL, a prática mais normal é evitar o uso da instrução "CREATE VIEW".
P: Em termos de desempenho - será pior, igual ou melhor em comparação com apenas inseri-lo em junções, subseleções etc?
R: Fazer referência a um objeto de exibição terá o desempenho idêntico a uma exibição em linha equivalente.
(Pode haver um pouquinho mais de trabalho para pesquisar o objeto de exibição, verificar privilégios e, em seguida, substituir a referência de exibição pelo SQL armazenado, em vez de enviar uma instrução que é apenas um pouquinho mais longa. Mas qualquer um desses diferenças são insignificantes.)
P: Existem desvantagens de ter uma visão neste caso?
R: A maior desvantagem está em como o MySQL processa uma visualização, seja ela armazenada ou inline. O MySQL sempre executará a consulta de visualização e materializará os resultados dessa consulta como uma tabela MyISAM temporária. Mas não há diferença se a definição de exibição é armazenada ou se está incluída em linha. (Outros RDBMSs processam visualizações muito diferentes do MySQL).
Uma grande desvantagem de uma visualização é que os predicados da consulta externa NUNCA são empurrados para a consulta de visualização. Toda vez que você faz referência a essa visualização, mesmo com uma consulta para um único valor de id, o MySQL executará a consulta de visualização e criará uma tabela MyISAM temporária (sem índices nela), e ENTÃO o MySQL executará a consulta externa contra essa tabela temporária tabela MyISAM.
Então, em termos de desempenho, pense em uma referência a uma visão a par com "
CREATE TEMPORARY TABLE t (cols) ENGINE=MyISAM
" e "INSERT INTO t (cols) SELECT ...
". MySQL na verdade se refere a uma visualização inline como uma "tabela derivada", e esse nome faz muito sentido, quando entendemos o que o MySQL está fazendo com ela.
Minha preferência pessoal é não usar a instrução "CREATE VIEW". A maior desvantagem (como eu vejo) é que ele "esconde" o SQL que está sendo executado. Para o futuro leitor, a referência à view se parece com uma tabela. E então, quando ele for escrever uma instrução SQL, ele fará referência à visão como se fosse uma tabela, muito conveniente. Então ele decide que vai juntar aquela mesa a ela mesma, com outra referência a ela. (Para a segunda referência, o MySQL também executa essa consulta novamente e cria outra tabela MyISAM temporária (e não indexada). E agora há uma operação JOIN nela. E então um predicado "WHERE view.column ='foo'" é adicionado na consulta externa.
Acaba "escondendo" a melhoria de desempenho mais óbvia, deslizando esse predicado para a consulta de visualização.
E então, alguém chega e decide que vai criar uma nova visão, que faz referência à visão antiga. Ele só precisa de um subconjunto de linhas e não pode modificar a visão existente porque isso pode quebrar alguma coisa, então ele cria uma nova visão... CREATE VIEW myview FROM publicview p WHERE p.col ='foo'.
E, agora, uma referência a myview vai primeiro executar a consulta publicview, criar uma tabela MyISAM temporária, então a consulta myview será executada contra isso, criando outra tabela MyISAM temporária, na qual a consulta externa será executada.
Basicamente, a conveniência da visualização tem o potencial de problemas de desempenho não intencionais. Com a definição de visualização disponível no banco de dados para qualquer pessoa usar, alguém a usará, mesmo quando não for a solução mais apropriada.
Pelo menos com uma visualização em linha, a pessoa que escreve a instrução SQL está mais ciente do SQL real que está sendo executado, e ter todo esse SQL definido oferece a oportunidade de ajustá-lo para desempenho.
Meus dois centavos.
DOMING BASTLY SQL
Acho que aplicar regras regulares de formatação (que minhas ferramentas fazem automaticamente) pode transformar o SQL monstruoso em algo que eu possa ler e trabalhar.
SELECT row.col1
, row.col2
, person.*
FROM some_table row
LEFT
JOIN ( SELECT 'person' AS `person_type`
, p.id AS `id`
, CONCAT(p.first_name,' ',p.surname) AS `name`
FROM person p
UNION ALL
SELECT 'company' AS `person_type`
, c.id AS `id`
, c.name AS `name`
FROM company c
) person
ON person.id = row.person_id
AND person.person_type = row.person_type
Eu teria a mesma probabilidade de evitar a exibição em linha e usar expressões condicionais na lista SELECT, embora isso fique mais complicado para muitas colunas.
SELECT row.col1
, row.col2
, row.person_type AS ref_person_type
, row.person_id AS ref_person_id
, CASE
WHEN row.person_type = 'person' THEN p.id
WHEN row.person_type = 'company' THEN c.id
END AS `person_id`
, CASE
WHEN row.person_type = 'person' THEN CONCAT(p.first_name,' ',p.surname)
WHEN row.person_type = 'company' THEN c.name
END AS `name`
FROM some_table row
LEFT
JOIN person p
ON row.person_type = 'person'
AND p.id = row.person_id
LEFT
JOIN company c
ON row.person_type = 'company'
AND c.id = row.person_id