Mysql
 sql >> Base de données >  >> RDS >> Mysql

L'index MySQL sur la vue ne fonctionne pas

Vous ne pouvez pas créer d'index sur une vue :http:/ /dev.mysql.com/doc/refman/5.7/en/view-restrictions.html , vous devez donc espérer que l'index est utilisé. https://stackoverflow.com/a/7922711/3595565

Solution

Il existe une solution de contournement mentionnée dans les commentaires d'une autre partie de la documentation :https://dev.mysql.com/doc/refman/5.5/en/create-view.html Dans lequel vous créez une table régulière et définissez votre index spécialisé et chargez les données de la vue dans la table.

LOCK TABLES materializedView WRITE; 
TRUNCATE materializedView; 
INSERT INTO materializedView SELECT * FROM regularView;
UNLOCK TABLES;

Pourquoi votre requête n'utilise-t-elle pas les index ?

Lors de l'utilisation de UNION dans un SELECT mysql crée une table temporaire pour enregistrer les données. Ainsi, comme une vue est un "raccourci" pour votre requête plus complexe, lors de l'appel de la sélection, elle exécutera à nouveau l'union, utilisera une table temporaire... utilisera l'algorithme temptable pour traiter les données.

Vérifiez à nouveau le manuel :http://dev.mysql. com/doc/refman/5.7/en/view-restrictions.html

Conclusion :L'UNION dans votre requête empêche la vue d'utiliser les index.

Sources

question sur le forum mysql pour le même problème réponse :

rapport de bogue "NE PAS CRÉER DE TABLES TEMPORAIRES POUR TOUTES LES UNIONS"

Correction dans MySQL 5.7 http:/ /dev.mysql.com/doc/relnotes/mysql/5.7/en/news-5-7-3.html

Quelques données de test pour vérifier le profileur

CREATE TABLE test1 (
    id int auto_increment PRIMARY KEY,
  col1 varchar(50),
  col2 varchar(50)
);

CREATE TABLE test2 (
    id int auto_increment PRIMARY KEY,
  col1 varchar(50),
  col2 varchar(50)
);

INSERT INTO test1 (col1, col2) 
VALUES 
('test', 'testcol2'),
('test', 'testcol2'),
('test', 'testcol2'),
('test', 'testcol2'),
('test', 'testcol2'),
('test', 'testcol2');


INSERT INTO test2 (col1, col2) 
VALUES 
('test2', 'testcol2'),
('test2', 'testcol2'),
('test2', 'testcol2'),
('test2', 'testcol2'),
('test2', 'testcol2'),
('test2', 'testcol2');

CREATE VIEW testview AS
SELECT * FROM test1
UNION
SELECT * FROM test2;

Vérifiez le profileur :

SET PROFILING = 1;
SELECT * FROM testview WHERE id = 1;
+----+-------+----------+
| id | col1  | col2     |
+----+-------+----------+
|  1 | test  | testcol2 |
|  1 | test2 | testcol2 |
+----+-------+----------+
SHOW PROFILE;
+--------------------------------+----------+
| Status                         | Duration |
+--------------------------------+----------+
| starting                       | 0.000017 |
| Waiting for query cache lock   | 0.000004 |
| checking query cache for query | 0.000029 |
| checking permissions           | 0.000006 |
| Opening tables                 | 0.000121 |
| System lock                    | 0.000012 |
| checking permissions           | 0.000014 |
| checking permissions           | 0.000032 |
| optimizing                     | 0.000004 |
| statistics                     | 0.000007 |
| preparing                      | 0.000006 |
| executing                      | 0.000003 |
| Sending data                   | 0.000046 |
| optimizing                     | 0.000003 |
| statistics                     | 0.000004 |
| preparing                      | 0.000003 |
| executing                      | 0.000002 |
| Sending data                   | 0.000023 |
| optimizing                     | 0.000003 |
| statistics                     | 0.000003 |
| preparing                      | 0.000003 |
| executing                      | 0.000002 |
| Sending data                   | 0.000008 |
| removing tmp table             | 0.000005 |
| Sending data                   | 0.000005 |
| Waiting for query cache lock   | 0.000002 |
| Sending data                   | 0.000024 |
| init                           | 0.000011 |
| optimizing                     | 0.000006 |
| statistics                     | 0.000004 |
| preparing                      | 0.000006 |
| executing                      | 0.000002 |
| Sending data                   | 0.000021 |
| end                            | 0.000003 |
| query end                      | 0.000004 |
| closing tables                 | 0.000002 |
| removing tmp table             | 0.000004 |
| closing tables                 | 0.000006 |
| freeing items                  | 0.000005 |
| Waiting for query cache lock   | 0.000003 |
| freeing items                  | 0.000013 |
| Waiting for query cache lock   | 0.000002 |
| freeing items                  | 0.000002 |
| storing result in query cache  | 0.000003 |
| logging slow query             | 0.000002 |
| cleaning up                    | 0.000003 |
+--------------------------------+----------+

Je ne peux pas retirer trop d'informations du profil, mais il mentionne une table temporaire, suffisamment (pour moi) pour valider ma conclusion.