Estoy de acuerdo con todos los puntos de la excelente respuesta de Bill Karwin.
P: ¿Es una práctica normal crear una vista para la consulta de unión discutida y usarla en mis uniones, subselecciones, etc.?
P: En términos de rendimiento, ¿será peor, igual o mejor en comparación con simplemente insertarlo en uniones, subselecciones, etc.?
(Puede haber un poquito más de trabajo para buscar el objeto de la vista, verificar los privilegios y luego reemplazar la referencia de la vista con el SQL almacenado, en lugar de enviar una declaración que es solo un poquito más larga. Pero cualquiera de esos las diferencias son insignificantes.)
P: ¿Hay algún inconveniente de tener una vista en este caso?
Un gran inconveniente de una vista es que los predicados de la consulta externa NUNCA se insertan en la consulta de la vista. Cada vez que haga referencia a esa vista, incluso con una consulta para un solo valor de identificación, MySQL ejecutará la consulta de vista y creará una tabla MyISAM temporal (sin índices), y LUEGO MySQL ejecutará la consulta externa contra ese temporal. Tabla MyISAM.
Entonces, en términos de rendimiento, piense en una referencia a una vista a la par con "CREATE TEMPORARY TABLE t (cols) ENGINE=MyISAM
" y "INSERT INTO t (cols) SELECT ...
".
MySQL en realidad se refiere a una vista en línea como una "tabla derivada", y ese nombre tiene mucho sentido, cuando entendemos qué está haciendo MySQL con ella.
Mi preferencia personal es no usar la instrucción "CREATE VIEW". El mayor inconveniente (tal como lo veo) es que "oculta" el SQL que se está ejecutando. Para el futuro lector, la referencia a la vista parece una tabla. Y luego, cuando vaya a escribir una instrucción SQL, hará referencia a la vista como si fuera una tabla, muy conveniente. Luego decide que va a unir esa tabla a sí misma, con otra referencia a ella. (Para la segunda referencia, MySQL también ejecuta esa consulta nuevamente y crea otra tabla MyISAM temporal (y no indexada). Y ahora hay una operación JOIN en eso. Y luego se agrega un predicado "WHERE view.column ='foo'" en la consulta externa.
Termina "ocultando" la mejora de rendimiento más obvia, deslizando ese predicado en la consulta de vista.
Y luego, alguien llega y decide que va a crear una nueva vista, que hace referencia a la vista anterior. Solo necesita un subconjunto de filas y no puede modificar la vista existente porque eso podría romper algo, por lo que crea una nueva vista... CREATE VIEW myview FROM publicview p WHERE p.col ='foo'.
Y, ahora, una referencia a myview primero ejecutará la consulta publicview, creará una tabla MyISAM temporal, luego la consulta myview se ejecutará contra eso, creando otra tabla MyISAM temporal, contra la cual se ejecutará la consulta externa.
Básicamente, la conveniencia de la vista tiene el potencial de problemas de rendimiento no intencionales. Con la definición de vista disponible en la base de datos para que cualquiera la use, alguien la usará, incluso cuando no sea la solución más adecuada.
Al menos con una vista en línea, la persona que escribe la instrucción SQL es más consciente del SQL real que se está ejecutando, y tener todo ese SQL dispuesto brinda la oportunidad de ajustarlo para mejorar el rendimiento.
Mis dos centavos.
DOMINAR A LA BESTIA SQL
Encuentro que aplicar reglas de formato regulares (que mis herramientas hacen automáticamente) puede convertir un SQL monstruoso en algo que pueda leer y trabajar.
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
Es igualmente probable que evite la vista en línea y use expresiones condicionales en la lista SELECT, aunque esto se vuelve más difícil de manejar para muchas columnas.
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