Joining a function and a view

The*_*ice 5 postgresql performance execution-plan plpgsql

我有一个功能 get_sa001 and a view Axis_RefCustomer.

当我get_sa001在一段时间内单独执行我的函数时,比如说 2016 - 2017,执行时间约为 6 秒。

SELECT d."Selling_date",  d."Value_in_EUR", d."Value_in_currency", d."Site"
FROM report.get_sa001('2016-01-01'::date, '2017-03-31'::date, 32) AS d
Run Code Online (Sandbox Code Playgroud)

当我在视图上执行选择时Axis_RefCustomer,它运行大约 1 秒。

Select a."Selling_currency" FROM report."Axis_RefCustomer" AS a
Run Code Online (Sandbox Code Playgroud)

当我将它们连接在一起时,执行时间约为 39 秒!

SELECT d."Selling_date",
a."Selling_currency", 
d."Value_in_EUR", 
d."Value_in_currency", 
d."Site"
FROM report.get_sa001('2016-01-01'::date, '2017-03-31'::date, 32) AS d 
LEFT JOIN report."Axis_RefCustomer" 
AS a ON d."Site" = a."Site" 
AND d."Internal_reference" = a."Reference_internal" 
AND d."Customer_code" = a."Customer_code"
Run Code Online (Sandbox Code Playgroud)

Is there anyway to reduce the amount of time my query takes to execute ?

我的函数的作用:我的函数从我作为参数输入的日期收集数据并将它们与视图相关联,然后它向我发送回我在 3rd 方应用程序上使用的表。

这是我自己对 2016 - 2017 年函数的解释分析:


Function Scan on get_sa001 d  (cost=0.25..10.25 rows=1000 width=104) (actual time=2522.959..2534.987 rows=53446 loops=1)
Total runtime: 2537.926 ms
Run Code Online (Sandbox Code Playgroud)

这是我对其自身观点的解释分析:


Hash Right Join  (cost=3527.82..5840.32 rows=74513 width=4) (actual time=47.363..71.317 rows=77965 loops=1)
    Hash Cond: ((("T12_RefCustomer"."Site")::text = ("T01_References"."Site")::text) AND (("T12_RefCustomer"."Internal_reference")::text = ("T01_References"."Internal_reference")::text))
    ->  Seq Scan on "T12_RefCustomer"  (cost=0.00..348.81 rows=13181 width=29) (actual time=0.002..2.350 rows=13182 loops=1)
    ->  Hash  (cost=1973.13..1973.13 rows=74513 width=22) (actual time=46.591..46.591 rows=74513 loops=1)
            Buckets: 2048  Batches: 4  Memory Usage: 1019kB
            ->  Seq Scan on "T01_References"  (cost=0.00..1973.13 rows=74513 width=22) (actual time=0.014..18.580 rows=74513 loops=1)
    Total runtime: 72.540 ms    
Run Code Online (Sandbox Code Playgroud)

这是我使用左连接对查询进行的解释分析:


Nested Loop Left Join  (cost=1.23..2375.17 rows=1000 width=108) (actual time=2406.131..42314.297 rows=53446 loops=1)
  ->  Function Scan on get_sa001 d  (cost=0.25..10.25 rows=1000 width=168) (actual time=2405.980..2429.250 rows=53446 loops=1)
  ->  Nested Loop  (cost=0.98..2.35 rows=1 width=28) (actual time=0.547..0.746 rows=1 loops=53446)
        Join Filter: (((d."Site")::text = ("T01_References"."Site")::text) AND ((d."Internal_reference")::text = ("T01_References"."Internal_reference")::text) AND (("T02_Customers"."Site")::text = ("T01_References"."Site")::text))
        Rows Removed by Join Filter: 126"
        ->  Nested Loop  (cost=0.57..1.42 rows=1 width=33) (actual time=0.011..0.057 rows=127 loops=53446)
              ->  Index Scan using "T02_Customers_pkey" on "T02_Customers"  (cost=0.28..0.77 rows=1 width=17) (actual time=0.004..0.004 rows=1 loops=53446)
                    Index Cond: ((d."Customer_code")::text = ("Customer_code")::text)
              ->  Index Scan using "T12_RefCustomer_pkey" on "T12_RefCustomer"  (cost=0.29..0.64 rows=1 width=29) (actual time=0.007..0.027 rows=99 loops=68927)
                    Index Cond: ((("Customer_code")::text = ("T02_Customers"."Customer_code")::text) AND (("Site")::text = ("T02_Customers"."Site")::text))
        ->  Index Scan using "T01_References_pkey" on "T01_References"  (cost=0.42..0.92 rows=1 width=22) (actual time=0.005..0.005 rows=1 loops=6795220)
              Index Cond: ((("Internal_reference")::text = ("T12_RefCustomer"."Internal_reference")::text) AND (("Site")::text = ("T12_RefCustomer"."Site")::text))
Total runtime: 42318.196 ms  
Run Code Online (Sandbox Code Playgroud)

我所做的:我已经清空了我的表并重新索引了它们,但结果没有改变。

小智 4

您尝试过使用 CTE 吗?我多次发现,在尝试连接之前减小数据集的大小可以大大缩短查询时间。

with
    __d as(
        select
            "Selling_date",
            "Value_in_EUR",
            "Value_in_currency",
            "Site",
            "Internal_reference",
            "Customer_code"
        from
            report.get_sa001('2016-01-01'::date, '2017-03-31'::date, 32)
    ),
    __a as(
        select
            "Selling_currency",
            "Site",
            "Reference_internal" as "Internal_reference",
            "Customer_code"
        from
            report."Axis_RefCustomer"
        where
            ("Site", "Reference_internal", "Customer_code") in(
                select
                    "Site",
                    "Internal_reference",
                    "Customer_code"
                from
                    __d
            )
    )
select
    __d."Selling_date",
    __a."Selling_currency", 
    __d."Value_in_EUR", 
    __d."Value_in_currency", 
    __d."Site"
from
    __d
    left join __a using("Site", "Internal_reference", "Customer_code")
Run Code Online (Sandbox Code Playgroud)