Ist MySQL Ansicht immer scanne vollständige Tabelle?
-
10-07-2019 - |
Frage
Ich versuche, eine Abfrage zu optimieren, die einen Blick in MySQL 5.1 verwendet. Es scheint, dass selbst wenn ich 1 Spalte aus der Ansicht auswählen tut es immer einen vollständigen Tabellenscan. Ist das das erwartete Verhalten?
Die Ansicht ist nur eine SELECT. „Alle Spalten aus diesen Tabellen - NOT *“ für die Tabellen I unten in der ersten Abfrage angegeben habe,
Das ist mein erklären Ausgabe aus, wenn ich die indexierte Spalte PromotionID aus der Abfrage wählen, die die Ansicht bildet. Wie Sie sehen, es von dem Ausgang auf der Ansicht, ganz anders ist.
EXPLAIN SELECT pb.PromotionID FROM PromotionBase pb INNER JOIN PromotionCart pct ON pb.PromotionID = pct.PromotionID INNER JOIN PromotionCode pc ON pb.PromotionID = pc.PromotionID WHERE pc.PromotionCode = '5TAFF312C0NT'\G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: pc
type: const
possible_keys: PRIMARY,fk_pc_pb
key: PRIMARY
key_len: 302
ref: const
rows: 1
Extra:
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: pb
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 1
Extra: Using index
*************************** 3. row ***************************
id: 1
select_type: SIMPLE
table: pct
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 1
Extra: Using index
3 rows in set (0.00 sec)
Die Ausgabe, wenn ich wählen Sie das Gleiche, aber aus der Sicht
EXPLAIN SELECT vpc.PromotionID FROM vw_PromotionCode vpc WHERE vpc.PromotionCode = '5TAFF312C0NT'\G;
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: <derived2>
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 5830
Extra: Using where
*************************** 2. row ***************************
id: 2
select_type: DERIVED
table: pcart
type: index
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: NULL
rows: 33
Extra: Using index
*************************** 3. row ***************************
id: 2
select_type: DERIVED
table: pb
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: readyinteractive.pcart.PromotionID
rows: 1
Extra:
*************************** 4. row ***************************
id: 2
select_type: DERIVED
table: pc
type: ref
possible_keys: fk_pc_pb
key: fk_pc_pb
key_len: 4
ref: readyinteractive.pb.PromotionID
rows: 249
Extra: Using where
*************************** 5. row ***************************
id: 3
select_type: UNION
table: pp
type: index
possible_keys: PRIMARY
key: pp_p
key_len: 4
ref: NULL
rows: 1
Extra: Using index
*************************** 6. row ***************************
id: 3
select_type: UNION
table: pb
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: readyinteractive.pp.PromotionID
rows: 1
Extra:
*************************** 7. row ***************************
id: 3
select_type: UNION
table: pc
type: ref
possible_keys: fk_pc_pb
key: fk_pc_pb
key_len: 4
ref: readyinteractive.pb.PromotionID
rows: 249
Extra: Using where
*************************** 8. row ***************************
id: 4
select_type: UNION
table: pcp
type: index
possible_keys: PRIMARY
key: pcp_cp
key_len: 4
ref: NULL
rows: 1
Extra: Using index
*************************** 9. row ***************************
id: 4
select_type: UNION
table: pb
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: readyinteractive.pcp.PromotionID
rows: 1
Extra:
*************************** 10. row ***************************
id: 4
select_type: UNION
table: pc
type: ref
possible_keys: fk_pc_pb
key: fk_pc_pb
key_len: 4
ref: readyinteractive.pb.PromotionID
rows: 249
Extra: Using where
*************************** 11. row ***************************
id: 5
select_type: UNION
table: ppc
type: index
possible_keys: PRIMARY
key: ppc_pc
key_len: 4
ref: NULL
rows: 1
Extra: Using index
*************************** 12. row ***************************
id: 5
select_type: UNION
table: pb
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: readyinteractive.ppc.PromotionID
rows: 1
Extra:
*************************** 13. row ***************************
id: 5
select_type: UNION
table: pc
type: ref
possible_keys: fk_pc_pb
key: fk_pc_pb
key_len: 4
ref: readyinteractive.pb.PromotionID
rows: 249
Extra: Using where
*************************** 14. row ***************************
id: 6
select_type: UNION
table: ppt
type: index
possible_keys: PRIMARY
key: ppt_pt
key_len: 4
ref: NULL
rows: 1
Extra: Using index
*************************** 15. row ***************************
id: 6
select_type: UNION
table: pb
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: readyinteractive.ppt.PromotionID
rows: 1
Extra:
*************************** 16. row ***************************
id: 6
select_type: UNION
table: pc
type: ref
possible_keys: fk_pc_pb
key: fk_pc_pb
key_len: 4
ref: readyinteractive.pb.PromotionID
rows: 249
Extra: Using where
*************************** 17. row ***************************
id: NULL
select_type: UNION RESULT
table: <union2,3,4,5,6>
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: NULL
Extra:
17 rows in set (0.18 sec)
Lösung
Views in MySQL indiziert sind nicht so von ihrem Wesen benötigen Sie einen Scan jedes Mal auf sie zugegriffen wird. Generell dies für Situationen Ansichten wirklich nur nützlich macht, wo man eine ziemlich komplexe statische Abfrage eine kleine Ergebnismenge zurückgibt und Sie planen, das gesamte Ergebnis jedes Mal eingestellt greifen.
Bearbeiten: Natürlich Ansichten werden die Indizes auf den zugrunde liegenden Tabellen verwenden, so dass die Ansicht selbst optimiert ist (sonst würden sie keinen Sinn überhaupt zu benutzen), sondern weil es keine Indizes auf einem Blick ist es für eine WHERE-Abfrage auf der Ansicht optimiert werden nicht möglich.
Indizes für Ansichten Constructing teuer wäre sowieso da, während ich keine Ansichten zum Profil habe es versucht, ich ziemlich sicher bin, dass eine temporäre Tabelle hinter den Kulissen aufgebaut ist, und dann wird das Ergebnis zurückgegeben. Es ist bereits viel Zeit in Anspruch nimmt, die temporäre Tabelle zu konstruieren, würde ich nicht einen Blick will, die auch zu erraten versucht, welche Indizes benötigt werden. Das bringt den zweiten Punkt, der ist, dass MySQL derzeit nicht ein Verfahren anzugeben bieten, was Indizes für eine Ansicht zu verwenden, so wie kennt es, welche Felder indiziert werden? Hat denke, es basiert auf Ihrer Anfrage?
Sie sollten erwägen eine rel="noreferrer"> weil dann können Sie Indizes für Felder in der temporären Tabelle angeben. Doch aus Erfahrung neigt dies wirklich zu sein, sehr langsam.
Wenn alle diese Ansicht enthält eine SELECT ALL FROM table1 ist, table2, table3; Ich würde dann fragen, warum diese Abfrage in einer Ansicht überhaupt sein muss? Wenn aus irgendeinem Grund seine absolut notwendig, können Sie eine gespeicherte Prozedur verwenden, um die Abfrage zu verkapseln, wie Sie dann in der Lage sein werden optimierte Leistung zu erhalten, während der Vorteil einer einfacheren Aufruf an die Datenbank für die Ergebnismenge beibehalten wird.
Andere Tipps
Ich habe sehe tiefer in sie eine I einen wichtigen Punkt von Informationen verpaßt habe :( Meine Ansicht Abfrage hat tatsächlich eine Vereinigung mit einem anderen Tisch. Dies führt zu der Ansicht, den TEMPORARY TABLE-Algorithmus anstelle des MERGE-Algorithmus zu verwenden.
Die TEMPORARY TABLE-Algorithmus ist die Verwendung von Indizes in den zugrundeliegenden Tabellen nicht zulassen.
Dies scheint ein Fehler in MySQL zu sein, und wurde im Jahr 2006 berichtet Weg zurück, aber sieht nicht wie es im Jahr 2009 gelöst wurde! http://forums.mysql.com/read.php?100,56681, 56681
Sieht aus wie ich bin nur beitreten gehen zu müssen, um die Abfrage als äußere neu schreiben.