Je suis d'accord avec tous les points de l'excellente réponse de Bill Karwin.
Q : Est-il normal de créer une vue pour la requête d'union discutée et de l'utiliser dans mes jointures, sous-sélections, etc. ?
R : Avec MySQL, la pratique la plus normale consiste à éviter d'utiliser l'instruction "CREATE VIEW".
Q : En termes de performances - sera-t-il pire, égal ou meilleur par rapport au simple fait de l'insérer dans des jointures, des sous-sélections, etc.?
R : Le référencement d'un objet de vue aura les mêmes performances qu'une vue en ligne équivalente.
(Il peut y avoir un tout petit peu plus de travail pour rechercher l'objet de vue, vérifier les privilèges, puis remplacer la référence de vue par le SQL stocké, par rapport à l'envoi d'une instruction qui est juste un tout petit peu plus longue. les différences sont insignifiantes.)
Q : Y a-t-il des inconvénients à avoir une vue dans ce cas ?
R : Le plus gros inconvénient réside dans la façon dont MySQL traite une vue, qu'elle soit stockée ou en ligne. MySQL exécutera toujours la requête de vue et matérialisera les résultats de cette requête sous la forme d'une table MyISAM temporaire. Mais il n'y a aucune différence si la définition de la vue est stockée ou si elle est incluse en ligne. (Les autres SGBDR traitent les vues très différemment de MySQL).
Un gros inconvénient d'une vue est que les prédicats de la requête externe ne sont JAMAIS poussés vers le bas dans la requête de vue. Chaque fois que vous faites référence à cette vue, même avec une requête pour une seule valeur d'identifiant, MySQL va exécuter la requête de vue et créer une table MyISAM temporaire (sans index dessus), et ALORS MySQL exécutera la requête externe sur cette valeur temporaire. Table MyISAM.
Donc, en termes de performances, pensez à une référence à une vue comparable à "CREATE TEMPORARY TABLE t (cols) ENGINE=MyISAM
" et "INSERT INTO t (cols) SELECT ...
".
MySQL fait en fait référence à une vue en ligne comme une "table dérivée", et ce nom a beaucoup de sens, quand on comprend ce que MySQL en fait.
Ma préférence personnelle est de ne pas utiliser l'instruction "CREATE VIEW". Le plus gros inconvénient (selon moi) est qu'il "cache" le SQL en cours d'exécution. Pour le futur lecteur, la référence à la vue ressemble à un tableau. Et puis, quand il va écrire une instruction SQL, il va référencer la vue comme si c'était une table, donc très pratique. Puis il décide qu'il va joindre cette table à elle-même, avec une autre référence à celle-ci. (Pour la deuxième référence, MySQL exécute également à nouveau cette requête et crée une autre table MyISAM temporaire (et non indexée). Et maintenant, il y a une opération JOIN à ce sujet. Et puis un prédicat "WHERE view.column ='foo'" est ajouté sur la requête externe.
Cela finit par "masquer" l'amélioration des performances la plus évidente, en glissant ce prédicat dans la requête de vue.
Et puis, quelqu'un arrive et décide qu'il va créer une nouvelle vue, qui fait référence à l'ancienne vue. Il n'a besoin que d'un sous-ensemble de lignes et ne peut pas modifier la vue existante car cela pourrait casser quelque chose. Il crée donc une nouvelle vue... CREATE VIEW myview FROM publicview p WHERE p.col ='foo'.
Et, maintenant, une référence à myview va d'abord exécuter la requête publicview, créer une table temporaire MyISAM, puis la requête myview est exécutée sur celle-ci, créant une autre table temporaire MyISAM, sur laquelle la requête externe va s'exécuter.
Fondamentalement, la commodité de la vue peut entraîner des problèmes de performances involontaires. Avec la définition de vue disponible sur la base de données pour que n'importe qui puisse l'utiliser, quelqu'un va l'utiliser, même si ce n'est pas la solution la plus appropriée.
Au moins avec une vue en ligne, la personne qui écrit l'instruction SQL est plus consciente du SQL réel en cours d'exécution, et le fait d'avoir tout ce SQL présenté donne la possibilité de l'ajuster pour les performances.
Mes deux sous.
APPRIVOISER BEASTLY SQL
Je trouve que l'application de règles de formatage régulières (que mes outils font automatiquement) peut transformer un code SQL monstrueux en quelque chose que je peux lire et utiliser.
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
Je serais tout aussi susceptible d'éviter la vue en ligne et d'utiliser des expressions conditionnelles dans la liste SELECT, bien que cela devienne plus compliqué pour de nombreuses colonnes.
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