簡體   English   中英

優化 SQL 查詢與同一張表上的子查詢

[英]Optimize SQL query with subquery on same table

我有以下 PostgreSQL

        EXPLAIN (ANALYZE, BUFFERS) select h.pk::varchar(255),
            (
                h.fecha at TIME zone 'Mexico/General' at TIME zone 'UTC'
            )::date as fecha
        from historial h
            where (
                h.fecha at TIME zone 'Mexico/General' at TIME zone 'UTC'
            )::date < '2022-07-30'
            and h.del = 0
            and (
                select COUNT(h.pk)
                from historial h
                where h.tipo in (3, 6, 9, 10)
                and h.del = 0
            ) > 10
         order by h.fkcr,
             h.fecha asc

但是歷史表有數百萬行,使用ORDER BY子句會導致時間從 ~300ms 跳轉到 ~6000ms!

是否可以對其進行優化?

這是命令的EXPLAIN (ANALYZE, BUFFERS)

我注意到排序節點正在使用磁盤對其進行排序,所以我嘗試將work_mem更改為 1GB,但它仍然使用磁盤,如果work_mem已經工作或者我誤解了 work_mem 的work_mem

QUERY PLAN                                                                                                                                      |
------------------------------------------------------------------------------------------------------------------------------------------------+
Sort  (cost=215616.65..217123.46 rows=602724 width=40) (actual time=11770.953..13789.063 rows=1810355 loops=1)                                  |
  Sort Key: h.fkcr, h.fecha                                                                                                                     |
  Sort Method: external merge  Disk: 145136kB                                                                                                   |
  Buffers: shared hit=16461 read=49282, temp read=32832 written=32832                                                                           |
  InitPlan 1 (returns $0)                                                                                                                       |
    ->  Aggregate  (cost=48588.68..48588.69 rows=1 width=16) (actual time=479.485..479.486 rows=1 loops=1)                                      |
          Buffers: shared hit=441 read=24000                                                                                                    |
          ->  Bitmap Heap Scan on historial h_1  (cost=3146.86..48088.10 rows=200230 width=16) (actual time=26.643..357.554 rows=186103 loops=1)|
                Recheck Cond: (tipo = ANY ('{3,6,9,10}'::integer[]))                                                                            |
                Filter: (del = 0)                                                                                                               |
                Rows Removed by Filter: 21311                                                                                                   |
                Heap Blocks: exact=23863                                                                                                        |
                Buffers: shared hit=441 read=24000                                                                                              |
                ->  Bitmap Index Scan on idx_tipo  (cost=0.00..3096.80 rows=208414 width=0) (actual time=22.107..22.107 rows=207414 loops=1)    |
                      Index Cond: (tipo = ANY ('{3,6,9,10}'::integer[]))                                                                        |
                      Buffers: shared hit=9 read=569                                                                                            |
  ->  Result  (cost=0.00..92681.53 rows=602724 width=40) (actual time=479.802..7149.979 rows=1810355 loops=1)                                   |
        One-Time Filter: ($0 > 10)                                                                                                              |
        Buffers: shared hit=16453 read=49282                                                                                                    |
        ->  Seq Scan on historial h  (cost=0.00..83640.67 rows=602724 width=40) (actual time=0.293..2781.099 rows=1810355 loops=1)              |
              Filter: ((del = 0) AND ((timezone('UTC'::text, timezone('Mexico/General'::text, fecha)))::date < '2022-07-30'::date))             |
              Rows Removed by Filter: 71719                                                                                                     |
              Buffers: shared hit=16012 read=25282                                                                                              |
Planning time: 1.105 ms                                                                                                                         |
Execution time: 14991.655 ms                                                                                                                    |

對於流程字段轉換或對字段進行任何操作,數據庫不能使用索引。 為此建議創建表達式索引。 例如:

CREATE INDEX historial_idx1 ON historial ((fecha at TIME zone 'Mexico/General' at TIME zone 'UTC')) 

或者

CREATE INDEX test_idx1 ON test ((id::text))

建議為此字段創建索引:

  1. 蒂波
  2. 德爾
  3. fecha - 表達指數
  4. fkcr, fecha (一起)

並建議對子查詢使用物化 CTE,例如:

with subquery as materialized (
    select COUNT(h.pk)
    from historial h
    where h.tipo in (3, 6, 9, 10)
    and h.del = 0 
) 
select h.pk::varchar(255),
(
    h.fecha at TIME zone 'Mexico/General' at TIME zone 'UTC'
)::date as fecha
from historial h
    where (
        h.fecha at TIME zone 'Mexico/General' at TIME zone 'UTC'
)::date < '2022-07-30'
    and h.del = 0
    and (select * from subquery) > 10
 order by h.fkcr,
     h.fecha asc

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM