Postgresql

使用許多連接提高查詢的性能

  • November 20, 2015

從以下解釋計劃:

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如果你買不起獨占鎖)基於這些索引的所有涉及的表至少一次。更多的:

索引列的順序很重要!

引用自:https://dba.stackexchange.com/questions/121237