Postgresql
使用許多連接提高查詢的性能
從以下解釋計劃:
explain SELECT imei, cliente_avl_equipo.id_cliente AS idcliente, cliente_avl_vehiculo.grupo AS grupo, avl_vehiculo.id, avl_vehiculo.id_clase, avl_vehiculo_clase.icono AS icono, avl_vehiculo.descripcion, avl_vehiculo.patente, avl_vehiculo.info, avl_vehiculo.conductor, avl_vehiculo.fijo_chasis, avl_vehiculo.enabled FROM cliente_avl_vehiculo,avl_vehiculo, avl_vehiculo_equipo, cliente_avl_equipo, avl_vehiculo_clase WHERE avl_vehiculo.id =avl_vehiculo_equipo.id AND cliente_avl_vehiculo.vehiculo_id=avl_vehiculo.id AND cliente_avl_equipo.imei_equipo =avl_vehiculo_equipo.imei AND avl_vehiculo_clase.id =avl_vehiculo.id_clase AND avl_vehiculo_equipo.imei =1234
我得到這樣的輸出:
Nested Loop (cost=0.00..22.57 rows=1 width=125 -> Nested Loop (cost=0.00..22.29 rows=1 width=67) -> Nested Loop (cost=0.00..14.92 rows=1 width=63) -> Nested Loop (cost=0.00..14.58 rows=1 width=63) -> Index Scan using fki_avl_vehiculo_equipo_imei on avl_vehiculo_equipo (cost=0.00..7.28 rows=1 width=12) Index Cond: (imei = 1234) -> Index Scan using index_avl_vehiculo_id on avl_vehiculo (cost=0.00..7.29 rows=1 width=51) Index Cond: (id = avl_vehiculo_equipo.id) -> Index Scan using index_cliente_avl_vehiculo_id on cliente_avl_vehiculo (cost=0.00..0.33 rows=1 width=8) Index Cond: (vehiculo_id = avl_vehiculo.id) -> Index Scan using fki_cliente_avl_equipo_imei on cliente_avl_equipo (cost=0.00..7.36 rows=1 width=12) Index Cond: (imei_equipo = 1234) -> Index Scan using index_avl_vehiculo_clase_id on avl_vehiculo_clase (cost=0.00..0.27 rows=1 width=62) Index Cond: (id = avl_vehiculo.id_clase)
我對解釋輸出不太熟悉,但這些
Index Scan
線對我來說似乎還可以,但我對這些線有疑問Nested Loop
,任何建議都會受到讚賞。
explain(analyze, verbose, buffers)
根據@a_horse_with_no_name的要求添加了輸出:Nested Loop (cost=0.00..22.57 rows=1 width=125) (actual time=0.122..0.122 rows=0 loops=1) Output: avl_vehiculo_equipo.imei, cliente_avl_equipo.id_cliente, cliente_avl_vehiculo.grupo, avl_vehiculo.id, avl_vehiculo.id_clase, avl_vehiculo_clase.icono, avl_vehiculo.descripcion, avl_vehiculo.patente, avl_vehiculo.info, avl_vehiculo.conductor, avl_ (...) Buffers: shared hit=6 -> Nested Loop (cost=0.00..22.29 rows=1 width=67) (actual time=0.121..0.121 rows=0 loops=1) Output: cliente_avl_vehiculo.grupo, avl_vehiculo.id, avl_vehiculo.id_clase, avl_vehiculo.descripcion, avl_vehiculo.patente, avl_vehiculo.info, avl_vehiculo.conductor, avl_vehiculo.fijo_chasis, avl_vehiculo.enabled, avl_vehiculo_equipo.imei, cliente (...) Buffers: shared hit=6 -> Nested Loop (cost=0.00..14.92 rows=1 width=63) (actual time=0.120..0.120 rows=0 loops=1) Output: cliente_avl_vehiculo.grupo, avl_vehiculo.id, avl_vehiculo.id_clase, avl_vehiculo.descripcion, avl_vehiculo.patente, avl_vehiculo.info, avl_vehiculo.conductor, avl_vehiculo.fijo_chasis, avl_vehiculo.enabled, avl_vehiculo_equipo.imei Buffers: shared hit=6 -> Nested Loop (cost=0.00..14.58 rows=1 width=63) (actual time=0.119..0.119 rows=0 loops=1) Output: avl_vehiculo.id, avl_vehiculo.id_clase, avl_vehiculo.descripcion, avl_vehiculo.patente, avl_vehiculo.info, avl_vehiculo.conductor, avl_vehiculo.fijo_chasis, avl_vehiculo.enabled, avl_vehiculo_equipo.imei, avl_vehiculo_equipo.id Buffers: shared hit=6 -> Index Scan using fki_avl_vehiculo_equipo_imei on public.avl_vehiculo_equipo (cost=0.00..7.28 rows=1 width=12) (actual time=0.118..0.118 rows=0 loops=1) Output: avl_vehiculo_equipo.imei, avl_vehiculo_equipo.id, avl_vehiculo_equipo.movil, avl_vehiculo_equipo.creation, avl_vehiculo_equipo.updated, avl_vehiculo_equipo.power_input, avl_vehiculo_equipo.ign_input, avl_vehiculo_equipo.po (...) Index Cond: (avl_vehiculo_equipo.imei = 1234) Buffers: shared hit=6 -> Index Scan using index_avl_vehiculo_id on public.avl_vehiculo (cost=0.00..7.29 rows=1 width=51) (never executed) Output: avl_vehiculo.id, avl_vehiculo.id_clase, avl_vehiculo.descripcion, avl_vehiculo.patente, avl_vehiculo.info, avl_vehiculo.numero, avl_vehiculo.conductor, avl_vehiculo.combustible, avl_vehiculo.consumo, avl_vehiculo.marca, av (...) Index Cond: (avl_vehiculo.id = avl_vehiculo_equipo.id) -> Index Scan using index_cliente_avl_vehiculo_id on public.cliente_avl_vehiculo (cost=0.00..0.33 rows=1 width=8) (never executed) Output: cliente_avl_vehiculo.cliente_rut, cliente_avl_vehiculo.vehiculo_id, cliente_avl_vehiculo.id_cliente, cliente_avl_vehiculo.grupo Index Cond: (cliente_avl_vehiculo.vehiculo_id = avl_vehiculo.id) -> Index Scan using fki_cliente_avl_equipo_imei on public.cliente_avl_equipo (cost=0.00..7.36 rows=1 width=12) (never executed) Output: cliente_avl_equipo.rut_cliente, cliente_avl_equipo.imei_equipo, cliente_avl_equipo.id_cliente Index Cond: (cliente_avl_equipo.imei_equipo = 1234) -> Index Scan using index_avl_vehiculo_clase_id on public.avl_vehiculo_clase (cost=0.00..0.27 rows=1 width=62) (never executed) Output: avl_vehiculo_clase.id, avl_vehiculo_clase.descripcion, avl_vehiculo_clase.categoria, avl_vehiculo_clase.icono Index Cond: (avl_vehiculo_clase.id = avl_vehiculo.id_clase) Total runtime: 1.535 ms
使用表別名、顯式 JOIN 語法、修剪噪音並格式化程式碼以使其易於閱讀:
SELECT ave.imei , cae.id_cliente AS idcliente -- odd alias? , cav.grupo , av.id , av.id_clase , avc.icono , av.descripcion , av.patente , av.info , av.conductor , av.fijo_chasis , av.enabled FROM avl_vehiculo_equipo ave JOIN cliente_avl_equipo cae ON cae.imei_equipo = ave.imei JOIN avl_vehiculo av ON av.id = ave.id JOIN cliente_avl_vehiculo cav ON cav.vehiculo_id = av.id JOIN avl_vehiculo_clase avc ON avc.id = av.id_clase WHERE ave.imei = 1234;
現在很明顯,除了 之外
avl_vehiculo
,您只需要每個表中的兩列,可能只是integer
列(這將是理想的)。要為此查詢優化最高讀取性能,請使用以下索引集:
ave(imei, id) -- index only scan cae(imei_equipo, id_cliente) -- index only scan av (id, id_clase) -- index scan cav(vehiculo_id, grupo) -- index only scan avc(id, icono) -- index only scan
假設 Postgres 9.2 或更高版本,並且如果滿足某些先決條件,您現在將獲得**除**
avl_vehiculo
.我會
CLUSTER
(或者pg_repack如果你買不起獨占鎖)基於這些索引的所有涉及的表至少一次。更多的:索引列的順序很重要!