2010-11-13 27 views
3

J'ai une vue contenant un UNION ALL. Par exemple:MySQL View contenant UNION n'optimise pas bien ... En d'autres termes, SLOW!

CRATE VIEW myView as 
(SELECT col1, col2, col3 
FROM tab1) 
UNION ALL 
(SELECT col1, col2, col3 
FROM tab2) 

Il s'agit de grandes tables contenant chacune 10 millions de lignes. Si je vous écris:

SELECT * 
FROM myView 
LIMIT 1; 

au lieu d'être immédiat, il revient essentiellement jamais comme d'autres requêtes écrites contre ce point de vue. Si j'utilise la LIMITE dans une requête sur les tables sous-jacentes individuelles, elle est immédiate. J'ai des index sur les tables sous-jacentes. Il semble que MySQL crée l'ensemble de données agrégées (requêtes dans la vue) pour la vue avant d'appliquer des critères de filtrage. C'est insensé. Est-ce la façon dont MySQL optimise les requêtes par rapport aux vues? En passant, je ne peux même pas exécuter un plan d'explication contre la vue parce qu'elle ne revient jamais.

Répondre

6

Le comportement que vous rencontrez est de savoir comment les vues non matérialisées sont gérées sur chaque base de données. MySQL ne supporte pas les vues matérialisées, et le support de vue n'est même pas à la hauteur des concurrents ...

Une vue non-matérialisée est juste un raccourci/macro/variable pour la requête qu'elle encapsule - il n'y a pas de différence entre en utilisant:

SELECT * 
    FROM myView 
LIMIT 1 

... et:

SELECT x.* 
    FROM (SELECT col1, col2, col3 
      FROM TAB1 
     UNION ALL 
     SELECT col1, col2, col3 
      FROM TAB2) x 
LIMIT 1 

Sans une clause ORDER BY, au mieux vous allez obtenir la première ligne basée sur l'insertion de votre requête, vous pourriez aussi bien être en cours d'exécution:

SELECT col1, col2, col3 
    FROM TAB1 
LIMIT 1 

... car il est peu probable de tirer des enregistrements à partir de TAB2 en raison de l'ordre des enregistrements renvoyés par une instruction UNIONed. Ensuite, il y a la question de traiter des dizaines de millions d'enregistrements ...