2009-03-12 12 views
6

Sto cercando di ottimizzare una query che utilizza una vista in MySQL 5.1. Sembra che anche se seleziono 1 colonna dalla vista, viene sempre eseguita una scansione completa della tabella. È questo il comportamento previsto?La vista MySQL esegue sempre la scansione completa della tabella?

La vista è solo un SELECT "Tutte le colonne da queste tabelle - NOT *" per le tabelle che ho specificato nella prima query di seguito.

Questo è il mio output di spiegare da quando seleziono la colonna indicizzata PromotionID dalla query che costituisce la vista. Come puoi vedere, è molto diverso dall'output della vista.

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) 

L'uscita quando seleziono la stessa cosa, ma dal punto di vista

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) 

risposta

9

Visualizzazioni in MySQL non vengono indicizzati in modo per loro natura richiedono una scansione completa ogni volta che si accede. In generale, ciò rende Views davvero utile solo per le situazioni in cui si dispone di una query statica abbastanza complessa che restituisce un piccolo set di risultati e si pianifica di acquisire l'intero set di risultati ogni volta.

Edit: Naturalmente Visualizzazioni utilizzeranno gli indici nelle tabelle sottostanti in modo che la vista in sé è ottimizzata (altrimenti non avrebbe alcun senso a tutti di utilizzare), ma perché non ci sono indici su un vederlo non è possibile per una query WHERE sulla vista da ottimizzare.

La creazione di indici per Views sarebbe comunque costosa perché mentre non ho provato a profilare alcuna vista, sono abbastanza certo che una tabella temporanea viene costruita dietro le quinte e quindi il set di risultati restituito. Ci vuole già un sacco di tempo per costruire la tabella temporanea, non vorrei una vista che cerchi anche di indovinare quali indici sono necessari. Il che evidenzia il secondo punto secondo cui MySQL attualmente non offre un metodo per specificare quali indici utilizzare per una vista, quindi come fa a sapere quali campi devono essere indicizzati? Indovina in base alla tua domanda?

È possibile utilizzare Temporary Table perché è possibile specificare indici sui campi nella tabella temporanea. Tuttavia, dall'esperienza questo tende ad essere veramente, molto lento.

Se tutta questa vista contiene è SELEZIONA TUTTO DA tabella1, tabella2, tabella3; quindi dovrei chiedere perché questa query deve essere in una vista a tutti? Se per qualche motivo è assolutamente necessario, è possibile utilizzare una stored procedure per incapsulare la query, in quanto sarà possibile ottenere prestazioni ottimizzate mantenendo il vantaggio di una chiamata più semplice al database per il set di risultati.

+0

Dice qui http://dev.mysql.com/doc/refman/5.0/en/view-restrictions.html che la vista utilizzerà gli indici delle tabelle sottostanti. – Alex

+0

Sono sicuro che hai ragione - le query sulle viste MySQL possono utilizzare gli indici dalle sue tabelle di origine.Non puoi semplicemente avere un indice sulla vista stessa e quindi non puoi avere un singolo indice contenente colonne da più di una di quelle tabelle. – thomasrutter

+0

Sfortunatamente questo non spiega perché quella seconda query sia così poco ottimizzata da MySQL. Tutto ciò a cui riesco a pensare è che forse questa visione non si sta unendo esattamente nel modo in cui è intesa. Non so però. – thomasrutter

3

Ho guardato più in profondità e ho perso un punto chiave di informazioni :(La mia query di visualizzazione ha effettivamente un'unione con un'altra tabella.Questo sta causando la visualizzazione di utilizzare l'algoritmo TEMPORARY TABLE invece dell'algoritmo MERGE .

l'algoritmo TEMPORARY TABLE non consente l'utilizzo di indici nelle tabelle sottostanti.

Questo sembra essere un bug in MySQL ed è stato segnalato nel lontano 2006, ma non sembra sia stato risolto nel 2009! http://forums.mysql.com/read.php?100,56681,56681

Sembra che dovrò solo riscrivere la query come un oute r join.

Problemi correlati