web-dev-qa-db-fra.com

Comment fonctionnent les vues MySQL?

Lorsque je crée une vue, je crée essentiellement une nouvelle table qui sera automatiquement traitée lorsque les données de l'une des tables qu'elle rejoint changeront; Est-ce exact?

Pourquoi ne puis-je pas utiliser de sous-requêtes à mon avis?

39
John Nall

Une vue fonctionne comme une table, mais ce n'est pas une table. Cela n'existe jamais; il s'agit uniquement d'une instruction SQL préparée qui est exécutée lorsque vous référencez le nom de la vue. C'EST À DIRE:

CREATE VIEW foo AS
  SELECT * FROM bar

SELECT * FROM foo

... équivaut à courir:

SELECT x.* 
  FROM (SELECT * FROM bar) x

Un MySQLDump ne contiendra jamais de lignes à insérer dans une vue ...

Aussi pourquoi ne puis-je pas utiliser de sous-requêtes à mon avis ????

Malheureusement, c'est par conception (quoique discutable). Il existe de nombreuses limitations pour les vues MySQL, qui sont documentées: http://dev.mysql.com/doc/refman/5.0/en/create-view.html

Donc, si c'est juste une table imaginaire/une instruction préparée, cela signifie-t-il qu'il a théoriquement les mêmes performances (ou même moins) qu'une table/requête normale?


Non.
Une table peut avoir des index associés, ce qui peut accélérer la récupération des données (à un certain coût pour l'insertion/la mise à jour). Certaines bases de données prennent en charge les vues "matérialisées", qui sont des vues auxquelles des index peuvent être appliqués - ce qui ne devrait pas être une surprise si MySQL ne prend pas en charge étant donné la fonctionnalité de vue limitée (qui n'a commencé que dans la v5 IIRC, très tard dans le jeu).

Dans la mesure où une vue est une table dérivée, les performances de la vue sont uniquement aussi bonnes que la requête sur laquelle elle est construite. Si cette requête est nulle, le problème de performances sera juste Snowball ... Cela dit, lors de l'interrogation d'une vue - si une référence de colonne de vue dans la clause WHERE n'est pas encapsulée dans une fonction (IE: WHERE v.column LIKE ..., pas WHERE LOWER(t.column) LIKE ...), l'optimiseur peut pousser les critères (appelés prédicats) sur la requête d'origine - ce qui les rend plus rapides.

53
OMG Ponies

J'ai également rencontré le même problème (à ma grande surprise, car ma recherche semble indiquer qu'Oracle et MS le prennent en charge).

Je contourne cette limitation (du moins pour l'instant, jusqu'à ce qu'elle soit prouvée non utilisable) en créant deux vues supplémentaires pour ma vue finale.

Exemple:

CREATE VIEW Foo1 AS
    SELECT * FROM t ORDER BY ID, InsertDate DESC

CREATE VIEW Foo2 AS
    SELECT * FROM Foo1 GROUP BY ID

CREATE VIEW Foo AS
    SELECT * FROM Foo2 ORDER BY ID

L'exemple ci-dessus a essentiellement une table "t" qui est une table temporelle contenant toutes les révisions. Mon 'Foo' (vue) est essentiellement une vue simple de mes révisions les plus récentes de chaque enregistrement. Semble bien fonctionner pour l'instant!

Mettre à jour:

Je ne sais pas s'il s'agit d'un autre bogue dans MySQL 5.1, mais l'exemple ci-dessus ne fonctionne pas en fait! Le 'Foo1' fonctionne comme prévu, mais le 'Foo2' semble ignorer l'ordre avant le regroupement, donc mon résultat final n'est pas ce qui est prévu. J'obtiens même le même résultat si je change le 'DESC' pour 'ASC' (étonnamment).

De plus, si vous lisez le 17.5.1. Afficher la syntaxe section, il indique clairement:

"Une vue peut être créée à partir de nombreux types d'instructions SELECT. Elle peut faire référence à des tables de base ou à d'autres vues. Elle peut utiliser des jointures, UNION et des sous-requêtes."

Je vais mettre à jour ma base de données vers 5.6 et réessayer!

2
Jeach

La différence est:

pour la vue, vous ne pouvez avoir des sous-requêtes que dans la partie où - pas dans la partie de - donc un

CREATE VIEW v AS SELECT * FROM foo WHERE id IN (SELECT id FROM bar) 

fonctionnerait - mais en même temps vous obtenez une vue en lecture seule ... Une vue simple sur une seule table permettrait de mettre à jour "à travers" la vue vers la table sous-jacente

2
eagle275