postgresql - 在查询中的两种情况下执行速度非常慢

标签 postgresql

计划查询:

Finalize Aggregate  (cost=20465.85..20465.86 rows=1 width=8) (actual time=21363.036..21363.037 rows=1 loops=1)
->  Gather  (cost=20465.63..20465.84 rows=2 width=8) (actual time=21363.014..21363.108 rows=3 loops=1)
    Workers Planned: 2
    Workers Launched: 2
    ->  Partial Aggregate  (cost=19465.63..19465.64 rows=1 width=8) (actual time=19548.388..19548.388 rows=1 loops=3)
          ->  Nested Loop  (cost=10766.23..19465.62 rows=6 width=0) (actual time=7204.795..19548.383 rows=1 loops=3)
                ->  Hash Join  (cost=10765.81..15255.58 rows=1142 width=16) (actual time=115.799..19505.353 rows=3937 loops=3)
                      Hash Cond: (exc.packageid = ex.id)
                      Join Filter: (ex1.notificationcontent ~~* (('%'::text || (CASE WHEN (exc.packageuid IS NOT NULL) THEN exc.packageuid ELSE ex.packageuid END)::text) || '%'::text))
                      Rows Removed by Join Filter: 1044143
                      ->  Merge Join  (cost=9575.89..13397.74 rows=254444 width=496) (actual time=104.064..456.209 rows=1048080 loops=3)
                            Merge Cond: (ex1.correspondent_uid = exc.correspondentuid)
                            ->  Sort  (cost=8011.08..8014.32 rows=1295 width=492) (actual time=96.345..97.537 rows=4011 loops=3)
                                  Sort Key: ex1.correspondent_uid
                                  Sort Method: quicksort  Memory: 5797kB
                                  ->  Parallel Seq Scan on ex_in ex1  (cost=0.00..7944.14 rows=1295 width=492) (actual time=0.082..90.635 rows=4011 loops=3)
                                        Filter: ((doctypeid = ANY ('{201,140005}'::integer[])) AND (notificationcontent ~~* '%success%'::text))
                                        Rows Removed by Filter: 12263
                            ->  Sort  (cost=1564.81..1596.49 rows=12675 width=36) (actual time=7.714..132.269 rows=1048164 loops=3)
                                  Sort Key: exc.correspondentuid
                                  Sort Method: quicksort  Memory: 1376kB
                                  ->  Seq Scan on ex_out_correspondents exc  (cost=0.00..701.03 rows=12675 width=36) (actual time=0.032..4.151 rows=12694 loops=3)
                                        Filter: (exchangestate = 2)
                                        Rows Removed by Filter: 20268
                      ->  Hash  (cost=884.00..884.00 rows=24473 width=36) (actual time=11.028..11.028 rows=24489 loops=3)
                            Buckets: 32768  Batches: 1  Memory Usage: 1874kB
                            ->  Seq Scan on ex_out ex  (cost=0.00..884.00 rows=24473 width=36) (actual time=0.025..6.597 rows=24489 loops=3)
                                  Filter: ((doctypeid < 200) AND (exchangetype = 7))
                                  Rows Removed by Filter: 2780
                ->  Index Scan using ipk__ds_documents__73ba3083 on ds_documents d  (cost=0.42..3.69 rows=1 width=16) (actual time=0.010..0.010 rows=0 loops=11811)
                      Index Cond: (uid = ex.docuid)
                      Filter: ((NOT pruz) AND ((reg_date)::date >= '2019-02-01'::date) AND ((reg_date)::date <= '2019-02-28'::date))
                      Rows Removed by Filter: 1

规划时间:4.169 毫秒 执行时间:21363.604 毫秒

如果我删除其中一个类似的条件,那么样本将在 100 毫秒内构建,而如果我保留这两个条件则需要 30 秒。

EXPLAIN(ANALYZE)
SELECT count(*)
FROM DS_DOCUMENTS d
INNER JOIN EX_Out ex ON d.UID = ex.DocUID and ExchangeType IN (7) and             DocTypeID < 200 and d.pruz = false
INNER JOIN EX_Out_Correspondents exc ON ex.ID = exc.PackageID and     exc.ExchangeState = 2 
INNER JOIN Ex_in ex1 ON ex1.Correspondent_UID = exc.CorrespondentUID 
    and ex1.DocTypeID in (201, 140005)  
    and ex1.NotificationContent ilike '%' || (case when exc.PackageUID is not null then exc.PackageUID else ex.PackageUID end)|| '%'
    and ex1.NotificationContent ilike '%success%'
WHERE cast(reg_date as date) between '01.02.2019' and '28.02.2019'

我做错了什么? 问题是在这种情况下,但我不知道为什么。

and ex1.NotificationContent ilike '%' || (case when exc.PackageUID is not null then exc.PackageUID else ex.PackageUID end)|| '%'
and ex1.NotificationContent ilike '%success%'

最佳答案

这是一个分段构建查询的示例,其想法是在添加昂贵的 JOIN 条件(如果可能的话应该对其进行优化)之前修剪工作集。我也尝试在 JOIN 之前处理 CASE 条件。 'success' 字符串是否位于 ex1.NotificationContent 中的公共(public)位置?如果是这样,请在第一个条件中应用它。

WITH d AS
(
    SELECT *
    FROM DS_DOCUMENTS d
    WHERE reg_date::date BETWEEN '01.02.2019' AND '28.02.2019'
), ex_exc AS
(
    SELECT  d.*     -- you may choose to select only the required fields in place of *
            , ex.*
            , exc.*
            , (CASE WHEN exc.PackageUID IS NOT NULL THEN exc.PackageUID ELSE ex.PackageUID END) AS join_package_uid
    FROM d
        JOIN EX_Out ex ON (d.UID = ex.DocUID 
                           AND ExchangeType = 7
                           AND DocTypeID < 200
                           AND d.pruz = FALSE
                          )
        JOIN EX_Out_Correspondents exc ON (ex.ID = exc.PackageID
                                           AND exc.ExchangeState = 2 
                                          )
)
SELECT count(*)
FROM ex_exc
    JOIN Ex_in ex1 ON (ex1.Correspondent_UID = exc.CorrespondentUID
                       AND ex1.DocTypeID IN (201, 140005)
                       AND ex1.NotificationContent ILIKE '%' || ex_exc.join_package_uid || '%'
                       AND ex1.NotificationContent ILIKE '%success%'
                      )
;

关于postgresql - 在查询中的两种情况下执行速度非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56855567/

相关文章:

sql - 设置 session 授权和搜索路径

postgresql - 在 JDBC 中将数组传递给 postgres

SQL 抽象出日期并在本周找到下一个

c# - Postgresql 和 .Net - 具有多个端点的连接池

sql - Postgresql,具有多个键的 jsonb 为每个键返回一行

Python/postgres/psycopg2 : getting ID of row just inserted

SQL按同一列中的多个项目进行过滤

postgresql - PostgreSQL 9.5 中的 integer 和 integer[] 有什么区别?

php - 过滤我的 postgreSQL 表

postgresql - Postgres : left join by unknown table - column value