Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Indeks MySQL na widoku nie działa

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.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Złączenie warunkowe mysql zależy od kolumny

  2. Zapytanie Mysqli ze zmienną SET (np. wiele zapytań)

  3. Jak mogę usunąć impas transakcyjny?

  4. Wstaw tablicę PDO używając klucza jako nazwy kolumny

  5. Za pomocą VBA znajdź wersję sterownika MySQL ODBC zainstalowaną w systemie Windows