Nie możesz utworzyć indeksu w widoku:http:// /dev.mysql.com/doc/refman/5.7/en/view-restrictions.html , więc musisz mieć nadzieję, że indeks jest używany. https://stackoverflow.com/a/7922711/3595565
Obejście
Istnieje obejście wspomniane w komentarzach do innej części dokumentacji:https://dev.mysql.com/doc/refman/5.5/en/create-view.html W którym tworzysz zwykłą tabelę i ustawiasz swój wyspecjalizowany indeks oraz ładujesz dane z widoku do tabeli.
LOCK TABLES materializedView WRITE;
TRUNCATE materializedView;
INSERT INTO materializedView SELECT * FROM regularView;
UNLOCK TABLES;
Dlaczego Twoje zapytanie nie korzysta z indeksów?
Podczas korzystania z UNION
w SELECT
mysql tworzy tymczasową tabelę do zapisywania danych. Tak więc, ponieważ widok jest "skrótem" dla bardziej złożonego zapytania, wywołanie select spowoduje ponowne wykonanie unii, użycie tymczasowej tabeli... użycie algorytmu temptable do przetwarzania danych.
Ponowne sprawdzenie instrukcji:http://dev.mysql. com/doc/refman/5.7/en/view-restrictions.html
Wniosek :UNION
w zapytaniu utrudnia widokowi korzystanie z indeksów.
Źródła
pytanie na forum mysql dotyczące tego samego problemu odpowiedź:
bugreport „NIE TWÓRZ TYMCZASOWYCH TABEL DLA WSZYSTKICH UNION”
Naprawiono w MySQL 5.7 http:// /dev.mysql.com/doc/relnotes/mysql/5.7/en/news-5-7-3.html
Niektóre dane testowe do sprawdzenia profilera
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;
Sprawdź profilera:
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 |
+--------------------------------+----------+
Nie mogę usunąć zbyt wielu informacji z profilu, ale wspomina się w nim o tabeli tymczasowej, wystarczająco (dla mnie), aby potwierdzić mój wniosek.