powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / NESTED LOOP и GroupAggregate
25 сообщений из 40, страница 1 из 2
NESTED LOOP и GroupAggregate
    #38882966
Nitro_Junkie
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Работаю с таким запросом (ниже приведу, лишь его часть, чтобы не перегружать):

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
SELECT t0.k0 AS jkey0,
       CASE
           WHEN t0.p0 IS NOT NULL THEN t0.p0
           WHEN (t1.e0 IS NOT NULL
                 AND t2.Sale_batchUserInvoiceDetail_UserInvoiceDetail IS NULL) THEN t1.e0
           ELSE NULL
       END AS jprop0
FROM t_10 t0
LEFT JOIN Sale_userInvoiceDetail t2 ON t2.key0=t0.k0
LEFT JOIN
  (SELECT t0.k0 AS k0,
          t1.PriceList_skuPriceListLedger_PriceListLedger AS k1,
          t0.k2 AS k2,
          LAST(t3.PriceList_pricePriceListLedgerLedgerPriceListType_PriceListLedg
               ORDER BY t1.PriceList_fromDateTimePriceListLedger_PriceListLedger ASC NULLS FIRST,t1.key0 ASC) AS e0
   FROM PriceList_priceListLedger t1
   JOIN
     (SELECT t0.Sale_supplierStockUserInvoiceDetail_null AS k0,
             t0.Sale_skuUserInvoiceDetail_UserInvoiceDetail AS k1,
             t0.Sale_dateTimeUserInvoiceDetail_null AS k2,
             ANYVALUE(1) AS e0
      FROM Sale_userInvoiceDetail t0
      JOIN t_10 t1 ON t1.k0=t0.key0
      WHERE (t0.Sale_supplierStockUserInvoiceDetail_null IS NOT NULL
             AND t0.Sale_skuUserInvoiceDetail_UserInvoiceDetail IS NOT NULL
             AND t0.Sale_dateTimeUserInvoiceDetail_null IS NOT NULL)
      GROUP BY 1,
               2,
               3) t0 ON t0.k1=t1.PriceList_skuPriceListLedger_PriceListLedger
   JOIN PriceList_priceListLedgerLedgerPriceListTypeStock t2 ON t2.key1=457
   AND t2.key2=t0.k0
   AND t2.key0=t1.key0
   LEFT JOIN PriceList_priceListLedgerLedgerPriceListType t3 ON t3.key0=t1.key0
   AND t3.key1=457
   WHERE ((t0.k2>t1.PriceList_fromDateTimePriceListLedger_PriceListLedger)
          AND ((t1.PriceList_toDateTimePriceListLedger_PriceListLedger IS NULL
                OR NOT t0.k2>t1.PriceList_toDateTimePriceListLedger_PriceListLedger))
          AND t2.PriceList_activePriceListLedgerLedgerPriceListTypeStock_null_nu IS NOT NULL
          AND t0.e0 IS NOT NULL)
   GROUP BY 1,
            2,
            3) t1 ON t1.k0=t2.Sale_supplierStockUserInvoiceDetail_null
AND t1.k1=t2.Sale_skuUserInvoiceDetail_UserInvoiceDetail
AND t1.k2=t2.Sale_dateTimeUserInvoiceDetail_null
LEFT JOIN PriceList_ledgerPriceListTypeStock t3 ON t3.key1=t2.Sale_supplierStockUserInvoiceDetail_null
AND t3.key0=457
LEFT JOIN Stock_batch t5 ON t5.key0=t2.Sale_batchUserInvoiceDetail_UserInvoiceDetail



План у него получается следующий (опять таки кусок касающийся этой части запроса):
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
65 t Insert on pg_temp_6.t_12  (cost=144875.29..144882.24 rows=327 width=49) (actual time=53453.065..53453.065 rows=0 loops=1)
65 t   ->  Merge Left Join  (cost=144875.29..144882.24 rows=327 width=49) (actual time=53440.192..53452.345 rows=327 loops=1)
65           Output: CASE WHEN (t0.p0 IS NOT NULL) THEN t0.p0 WHEN ((t1.e0 IS NOT NULL) AND (t2.sale_batchuserinvoicedetail_userinvoicedetail IS NULL)) THEN t1.e0 ELSE NULL::numeric END, t0.k0
66           Merge Cond: ((t2.sale_supplierstockuserinvoicedetail_null = t1.k0) AND (t2.sale_datetimeuserinvoicedetail_null = t1.k2))
66           Join Filter: (t1.k1 = t2.sale_skuuserinvoicedetail_userinvoicedetail)
66           Rows Removed by Join Filter: 104967
66           Filter: (((t1.e0 IS NOT NULL) AND (t2.sale_batchuserinvoicedetail_userinvoicedetail IS NULL)) OR ((t3.pricelist_batchledgerpricelisttypestock_ledgerpricelisttype_sto IS NULL) AND ((last(t3_1.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg ORDER BY t1_1.pricelist_fromdatetimepricelistledger_pricelistledger NULLS FIRST, t1_1.key0)) IS NOT NULL)) OR (((last(t4.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg ORDER BY t2_3.pricelist_fromdatetimepricelistledger_pricelistledger NULLS FIRST, t1_3.key0)) IS NOT NULL) AND (t3.pricelist_batchledgerpricelisttypestock_ledgerpricelisttype_sto IS NOT NULL)) OR (t0.p0 IS NOT NULL))
66 t         ->  Merge Left Join  (cost=95041.82..95046.26 rows=327 width=101) (actual time=53249.709..53250.690 rows=327 loops=1)
66                 Output: t0.p0, t0.k0, t2.sale_batchuserinvoicedetail_userinvoicedetail, t2.sale_supplierstockuserinvoicedetail_null, t2.sale_skuuserinvoicedetail_userinvoicedetail, t2.sale_datetimeuserinvoicedetail_null, t3.pricelist_batchledgerpricelisttypestock_ledgerpricelisttype_sto, (last(t3_1.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg ORDER BY t1_1.pricelist_fromdatetimepricelistledger_pricelistledger NULLS FIRST, t1_1.key0)), (last(t4.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg ORDER BY t2_3.pricelist_fromdatetimepricelistledger_pricelistledger NULLS FIRST, t1_3.key0))
67                 Merge Cond: ((t2.sale_supplierstockuserinvoicedetail_null = t0_2.sale_supplierstockuserinvoicedetail_null) AND (t2.sale_datetimeuserinvoicedetail_null = t0_2.sale_datetimeuserinvoicedetail_null) AND (t2.sale_batchuserinvoicedetail_userinvoicedetail = t0_2.sale_batchuserinvoicedetail_userinvoicedetail))
67 t               ->  Sort  (cost=50569.17..50569.99 rows=327 width=69) (actual time=53104.693..53104.702 rows=327 loops=1)
67                       Output: t0.p0, t0.k0, t2.sale_batchuserinvoicedetail_userinvoicedetail, t2.sale_supplierstockuserinvoicedetail_null, t2.sale_skuuserinvoicedetail_userinvoicedetail, t2.sale_datetimeuserinvoicedetail_null, t3.pricelist_batchledgerpricelisttypestock_ledgerpricelisttype_sto, (last(t3_1.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg ORDER BY t1_1.pricelist_fromdatetimepricelistledger_pricelistledger NULLS FIRST, t1_1.key0))
67                       Sort Key: t2.sale_supplierstockuserinvoicedetail_null, t2.sale_datetimeuserinvoicedetail_null, t2.sale_batchuserinvoicedetail_userinvoicedetail
67                       Sort Method: quicksort  Memory: 70kB
68 t (!)                ->  Nested Loop Left Join  (cost=49972.27..50555.52 rows=327 width=69) (actual time=188.679..53104.349 rows=327 loops=1)
68                             Output: t0.p0, t0.k0, t2.sale_batchuserinvoicedetail_userinvoicedetail, t2.sale_supplierstockuserinvoicedetail_null, t2.sale_skuuserinvoicedetail_userinvoicedetail, t2.sale_datetimeuserinvoicedetail_null, t3.pricelist_batchledgerpricelisttypestock_ledgerpricelisttype_sto, (last(t3_1.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg ORDER BY t1_1.pricelist_fromdatetimepricelistledger_pricelistledger NULLS FIRST, t1_1.key0))
68                             ->  Seq Scan on pg_temp_6.t_10 t0  (cost=0.00..5.27 rows=327 width=13) (actual time=0.004..0.300 rows=327 loops=1)
68                                   Output: t0.p0, t0.k0
68 t                           ->  Hash Right Join  (cost=49972.27..49974.03 rows=1 width=60) (actual time=161.978..162.363 rows=1 loops=327)
68                                   Output: t2.sale_batchuserinvoicedetail_userinvoicedetail, t2.key0, t2.sale_supplierstockuserinvoicedetail_null, t2.sale_skuuserinvoicedetail_userinvoicedetail, t2.sale_datetimeuserinvoicedetail_null, t3.pricelist_batchledgerpricelisttypestock_ledgerpricelisttype_sto, (last(t3_1.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg ORDER BY t1_1.pricelist_fromdatetimepricelistledger_pricelistledger NULLS FIRST, t1_1.key0))
69                                   Hash Cond: ((t1_2.sale_supplierstockuserinvoicedetail_null = t2.sale_supplierstockuserinvoicedetail_null) AND (t1_1.pricelist_skupricelistledger_pricelistledger = t5.stock_skubatch_batch) AND (t1_2.sale_datetimeuserinvoicedetail_null = t2.sale_datetimeuserinvoicedetail_null))
69 t                                 ->  GroupAggregate  (cost=49964.12..49965.74 rows=6 width=35) (actual time=161.420..162.289 rows=322 loops=327 (!))
69                                         Output: t1_2.sale_supplierstockuserinvoicedetail_null, t1_1.pricelist_skupricelistledger_pricelistledger, t1_2.sale_datetimeuserinvoicedetail_null, last(t3_1.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg ORDER BY t1_1.pricelist_fromdatetimepricelistledger_pricelistledger NULLS FIRST, t1_1.key0)
69 G                                       ->  Sort  (cost=49964.12..49964.14 rows=6 width=35) (actual time=161.388..161.400 rows=545 loops=327 (!))
69                                               Output: t1_2.sale_supplierstockuserinvoicedetail_null, t1_1.pricelist_skupricelistledger_pricelistledger, t1_2.sale_datetimeuserinvoicedetail_null, t3_1.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg, t1_1.pricelist_fromdatetimepricelistledger_pricelistledger, t1_1.key0
69                                               Sort Key: t1_2.sale_supplierstockuserinvoicedetail_null, t1_1.pricelist_skupricelistledger_pricelistledger, t1_2.sale_datetimeuserinvoicedetail_null
70                                               Sort Method: quicksort  Memory: 67kB
70 G                                             ->  Nested Loop Left Join  (cost=33564.15..49964.05 rows=6 width=35) (actual time=73.204..161.193 rows=545 loops=327)
70                                                     Output: t1_2.sale_supplierstockuserinvoicedetail_null, t1_1.pricelist_skupricelistledger_pricelistledger, t1_2.sale_datetimeuserinvoicedetail_null, t3_1.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg, t1_1.pricelist_fromdatetimepricelistledger_pricelistledger, t1_1.key0
70 G                                                   ->  Hash Join  (cost=33563.72..49927.02 rows=6 width=28) (actual time=73.190..159.776 rows=545 loops=327)
70                                                           Output: t1_1.pricelist_skupricelistledger_pricelistledger, t1_1.pricelist_fromdatetimepricelistledger_pricelistledger, t1_1.key0, t1_2.sale_supplierstockuserinvoicedetail_null, t1_2.sale_datetimeuserinvoicedetail_null
70                                                           Hash Cond: ((t2_1.key2 = t1_2.sale_supplierstockuserinvoicedetail_null) AND (t2_1.key0 = t1_1.key0))
71                                                           ->  Bitmap Heap Scan on public.pricelist_pricelistledgerledgerpricelisttypestock t2_1  (cost=6352.55..20172.45 rows=339112 width=8) (actual time=13.590..54.387 rows=341492 loops=327)
71                                                                 Output: t2_1.key0, t2_1.key1, t2_1.key2, t2_1.pricelist_activepricelistledgerledgerpricelisttypestock_null_nu
71                                                                 Recheck Cond: (t2_1.key1 = 457)
71                                                                 Filter: (t2_1.pricelist_activepricelistledgerledgerpricelisttypestock_null_nu IS NOT NULL)
71                                                                 ->  Bitmap Index Scan on pricelist_pricelistledgerledgerpricelisttypestock_key1_key2_idx  (cost=0.00..6267.77 rows=339112 width=0) (actual time=12.943..12.943 rows=341492 loops=327)
71                                                                       Index Cond: (t2_1.key1 = 457)
72 G                                                         ->  Hash  (cost=27147.84..27147.84 rows=4222 width=28) (actual time=20.204..20.204 rows=27765 loops=327)
72                                                                 Output: t1_1.pricelist_skupricelistledger_pricelistledger, t1_1.pricelist_fromdatetimepricelistledger_pricelistledger, t1_1.key0, t1_2.sale_supplierstockuserinvoicedetail_null, t1_2.sale_datetimeuserinvoicedetail_null
72                                                                 Buckets: 1024  Batches: 2 (originally 1)  Memory Usage: 1025kB
72 G                                                               ->  Nested Loop  (cost=2779.21..27147.84 rows=4222 width=28) (actual time=0.018..15.330 rows=27765 loops=327)
72                                                                       Output: t1_1.pricelist_skupricelistledger_pricelistledger, t1_1.pricelist_fromdatetimepricelistledger_pricelistledger, t1_1.key0, t1_2.sale_supplierstockuserinvoicedetail_null, t1_2.sale_datetimeuserinvoicedetail_null
72                                                                       ->  HashAggregate  (cost=2778.78..2782.05 rows=327 width=16) (actual time=0.009..0.090 rows=322 loops=327)
73                                                                             Output: t1_2.sale_supplierstockuserinvoicedetail_null, t0_1.stock_skubatch_batch, t1_2.sale_datetimeuserinvoicedetail_null, anyvalue(1)
73                                                                             Filter: (anyvalue(1) IS NOT NULL)
73                                                                             ->  Nested Loop  (cost=0.71..2612.83 rows=327 width=16) (actual time=0.023..2.452 rows=327 loops=1)
73                                                                                   Output: t1_2.sale_supplierstockuserinvoicedetail_null, t1_2.sale_datetimeuserinvoicedetail_null, t0_1.stock_skubatch_batch
73                                                                                   ->  Nested Loop  (cost=0.42..2480.42 rows=327 width=16) (actual time=0.016..0.587 rows=327 loops=1)
73                                                                                         Output: t1_2.sale_supplierstockuserinvoicedetail_null, t1_2.sale_datetimeuserinvoicedetail_null, t1_2.sale_batchuserinvoicedetail_userinvoicedetail
74                                                                                         ->  Seq Scan on pg_temp_6.t_10 t2_2  (cost=0.00..5.27 rows=327 width=4) (actual time=0.005..0.024 rows=327 loops=1)
74                                                                                               Output: t2_2.p0, t2_2.k0
74                                                                                         ->  Index Scan using pk_sale_userinvoicedetail on public.sale_userinvoicedetail t1_2  (cost=0.42..7.56 rows=1 width=20) (actual time=0.001..0.001 rows=1 loops=327)
74                                                                                               Output: t1_2.*
75                                                                                               Index Cond: (t1_2.key0 = t2_2.k0)
75                                                                                               Filter: ((t1_2.sale_supplierstockuserinvoicedetail_null IS NOT NULL) AND (t1_2.sale_datetimeuserinvoicedetail_null IS NOT NULL))
75                                                                                   ->  Index Scan using pk_stock_batch on public.stock_batch t0_1  (cost=0.29..0.39 rows=1 width=8) (actual time=0.005..0.005 rows=1 loops=327)
75                                                                                         Output: t0_1.*, ...
76                                                                                         Index Cond: (t0_1.key0 = t1_2.sale_batchuserinvoicedetail_userinvoicedetail)
76                                                                                         Filter: (t0_1.stock_skubatch_batch IS NOT NULL)
76                                                                       ->  Index Scan using pricelist_pricelistledger_pricelist_skupricelistledger_pricelis on public.pricelist_pricelistledger t1_1  (cost=0.43..74.37 rows=13 width=24) (actual time=0.003..0.042 rows=86 loops=105294)
76                                                                             Output: t1_1.key0, t1_1.pricelist_skupricelistledger_pricelistledger, t1_1.pricelist_ispostedpricelistledger_pricelistledger, t1_1.pricelist_todatetimepricelistledger_pricelistledger, t1_1.pricelist_fromdatetimepricelistledger_pricelistledger, t1_1.pricelist_skippricelistledger_pricelistledger, t1_1.pricelist_activepricelistledger_null, t1_1.pricelist_companypricelistledger_pricelistledger, t1_1.pricelist_descriptionpricelistledger_pricelistledger, t1_1.pricelist_companystockpricelistledger_pricelistledger
76                                                                             Index Cond: (t1_1.pricelist_skupricelistledger_pricelistledger = t0_1.stock_skubatch_batch)
76                                                                             Filter: ((t1_2.sale_datetimeuserinvoicedetail_null > t1_1.pricelist_fromdatetimepricelistledger_pricelistledger) AND ((t1_1.pricelist_todatetimepricelistledger_pricelistledger IS NULL) OR (t1_2.sale_datetimeuserinvoicedetail_null <= t1_1.pricelist_todatetimepricelistledger_pricelistledger)))
77                                                                             Rows Removed by Filter: 7
77                                                     ->  Index Scan using pk_pricelist_pricelistledgerledgerpricelisttype on public.pricelist_pricelistledgerledgerpricelisttype t3_1  (cost=0.43..6.16 rows=1 width=11) (actual time=0.002..0.002 rows=1 loops=178215)
77                                                           Output: t3_1.key0, t3_1.key1, t3_1.pricelist_inpricelistledgersystemledgerpricelisttype_pricelistl, t3_1.pricelist_inpricelistledgerledgerpricelisttype_pricelistledger_, t3_1.pricelist_pricepricelistledgersystemledgerpricelisttype_priceli, t3_1.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg, t3_1.pricelist_activepricelistledgerledgerpricelisttype_null_null
77                                                           Index Cond: ((t3_1.key0 = t1_1.key0) AND (t3_1.key1 = 457))
77                                   ->  Hash  (cost=8.13..8.13 rows=1 width=32) (actual time=0.031..0.031 rows=1 loops=327)
77                                         Output: t2.sale_batchuserinvoicedetail_userinvoicedetail, t2.key0, t2.sale_supplierstockuserinvoicedetail_null, t2.sale_skuuserinvoicedetail_userinvoicedetail, t2.sale_datetimeuserinvoicedetail_null, t3.pricelist_batchledgerpricelisttypestock_ledgerpricelisttype_sto, t5.stock_skubatch_batch
78                                         Buckets: 1024  Batches: 1  Memory Usage: 1kB
78                                         ->  Nested Loop Left Join  (cost=0.85..8.13 rows=1 width=32) (actual time=0.028..0.029 rows=1 loops=327)
78                                               Output: t2.sale_batchuserinvoicedetail_userinvoicedetail, t2.key0, t2.sale_supplierstockuserinvoicedetail_null, t2.sale_skuuserinvoicedetail_userinvoicedetail, t2.sale_datetimeuserinvoicedetail_null, t3.pricelist_batchledgerpricelisttypestock_ledgerpricelisttype_sto, t5.stock_skubatch_batch
78                                               ->  Nested Loop Left Join  (cost=0.56..7.73 rows=1 width=28) (actual time=0.013..0.014 rows=1 loops=327)
78                                                     Output: t2.sale_batchuserinvoicedetail_userinvoicedetail, t2.key0, t2.sale_supplierstockuserinvoicedetail_null, t2.sale_skuuserinvoicedetail_userinvoicedetail, t2.sale_datetimeuserinvoicedetail_null, t3.pricelist_batchledgerpricelisttypestock_ledgerpricelisttype_sto
79                                                     ->  Index Scan using pk_sale_userinvoicedetail on public.sale_userinvoicedetail t2  (cost=0.42..7.56 rows=1 width=24) (actual time=0.007..0.007 rows=1 loops=327)
79                                                           Output: t2.key0, ...
80                                                           Index Cond: (t2.key0 = t0.k0)
80                                                     ->  Index Scan using pk_pricelist_ledgerpricelisttypestock on public.pricelist_ledgerpricelisttypestock t3  (cost=0.14..0.16 rows=1 width=8) (actual time=0.003..0.003 rows=1 loops=327)
80                                                           Output: t3.key0, t3.key1, t3.pricelist_batchledgerpricelisttypestock_ledgerpricelisttype_sto
80                                                           Index Cond: ((t3.key0 = 457) AND (t3.key1 = t2.sale_supplierstockuserinvoicedetail_null))
80                                               ->  Index Scan using pk_stock_batch on public.stock_batch t5  (cost=0.29..0.39 rows=1 width=8) (actual time=0.013..0.013 rows=1 loops=327)
81                                                     Output: t5.key0, ...
81                                                     Index Cond: (t5.key0 = t2.sale_batchuserinvoicedetail_userinvoicedetail)



В сумме он выполняется 55 секунд. И происходит это из-за того что GroupAggregate выполняется 327 раз. Соответственно вопрос почему она не материализует GroupAggregate ? Cost же у него запредельный. Estimate маленький.

Или у PostgreSQL вообще нет такой возможности как materialize подзапроса и будет проблема в случае:

A (маленькая таблица, ключ k0) LJ B (огромная таблица, ключ k0, поле f0 без индекса) ON A.k0 = B.k0 LJ SQ (маленький но долго выполняемый подзапрос с ключом k0) ON SQ.k0 = B.f0

Потому как у нее 2 варианта

или высчитать SQ, а затем right join'ить с B что будет очень долго так как придется бежать по B (индекса там напомню нет, да и результат будет большой так что и индекс не поможет), после чего уже hash join'ить с A (план будет очень медленным)

или (то что мы видим тут) для всех A, ищем все записи B и для каждой (! так как materialize'а нет) из них выполняем SQ после чего right join'им результат с B (план также будет медленным из-за многочисленного выполнения SQ).
...
Рейтинг: 0 / 0
NESTED LOOP и GroupAggregate
    #38883005
Nitro_Junkie
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nitro_Junkie,

Я вообще правильно понимаю что во втором случае (и собственно в первом), она должна сделать так

Hash Right Join
Hash Cond SQ.k0 = B.f0
GroupAggregate (допустим группирующий подзапрос с таблицей SQ)
Hash
Nested Left Join
Seq scan A
Index scan B on индекс по k0
Index cond : B.k0 = A.k0
...
Рейтинг: 0 / 0
NESTED LOOP и GroupAggregate
    #38883006
Nitro_Junkie
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nitro_Junkie,

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
Hash Right Join
     Hash Cond SQ.k0 = B.f0
     GroupAggregate (допустим группирующий подзапрос с таблицей SQ)
     Hash
          Nested Left Join
               Seq scan A
               Index scan B on индекс по k0
                      Index cond : B.k0 = A.k0
...
Рейтинг: 0 / 0
NESTED LOOP и GroupAggregate
    #38883039
Nitro_Junkie
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nitro_JunkieNitro_Junkie,

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
Hash Right Join
     Hash Cond SQ.k0 = B.f0
     GroupAggregate (допустим группирующий подзапрос с таблицей SQ)
     Hash
          Nested Left Join
               Seq scan A
               Index scan B on индекс по k0
                      Index cond : B.k0 = A.k0



Проверил на других запросах, именно так она и должна делать, но почему здесь ее клинит загадка...
...
Рейтинг: 0 / 0
NESTED LOOP и GroupAggregate
    #38883043
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nitro_Junkie,

закиньте этот group by в WITH блок и будет вам материализация.

Но у меня есть идея почему он не материализует.
У вас функция ANYVALUE(1) случайно не volatile?

--Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
NESTED LOOP и GroupAggregate
    #38883051
Nitro_Junkie
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim BogukNitro_Junkie,

закиньте этот group by в WITH блок и будет вам материализация.

Но у меня есть идея почему он не материализует.
У вас функция ANYVALUE(1) случайно не volatile?

--Maxim Boguk
www.postgresql-consulting.ru

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
CREATE OR REPLACE FUNCTION getAnyNotNull(ANYELEMENT, ANYELEMENT) RETURNS ANYELEMENT AS
$$
  SELECT CASE WHEN $1 = NULL THEN $2 ELSE $1 END;
$$ LANGUAGE SQL STRICT;

DROP AGGREGATE IF EXISTS ANYVALUE (anyelement) CASCADE;
CREATE AGGREGATE ANYVALUE (anyelement) (
  sfunc = getAnyNotNull,
  stype = anyelement
);



Я вообще наблюдаю странное явление природы. В приложении запрос показывает такой план, запускаю в pgAdmin план уже нормальный, чудо какое-то...
...
Рейтинг: 0 / 0
NESTED LOOP и GroupAggregate
    #38883068
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Воообще совет... в таких ситуациях зачастую проще помочь планировщику и частично зафиксировать нужный вам план через WITH (в тех частях где вам 100% materialize нужен).
Ну и понимать что с стандартными настройками базы она только до 8 joins разворачивает/сворачивает а дальше начинается GEQO и угадает он с планом или нет никто не знает.
Так что для сложных запросов еще полезно join_collapse_limit/from_collapse_limit поднять слегка.

--Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
NESTED LOOP и GroupAggregate
    #38883092
Nitro_Junkie
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim BogukВоообще совет... в таких ситуациях зачастую проще помочь планировщику и частично зафиксировать нужный вам план через WITH (в тех частях где вам 100% materialize нужен).
Ну и понимать что с стандартными настройками базы она только до 8 joins разворачивает/сворачивает а дальше начинается GEQO и угадает он с планом или нет никто не знает.
Так что для сложных запросов еще полезно join_collapse_limit/from_collapse_limit поднять слегка.

--Maxim Boguk
www.postgresql-consulting.ru

Проблема в том что 100% materialize тяжеловато угадать.

Кстати словил ту же проблему на совсем простом запросе, то есть на GEQO не спишешь:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
SELECT t0.k0 AS jkey0,
       t0.p0 AS jprop0
FROM t_12 t0
LEFT JOIN Sale_userInvoiceDetail t2 ON t2.key0=t0.k0
LEFT JOIN
  (SELECT t1.PriceList_skuPriceListLedger_PriceListLedger AS k0,
          t0.k1 AS k1,
          t0.k2 AS k2,
          LAST(t3.PriceList_pricePriceListLedgerLedgerPriceListType_PriceListLedg
               ORDER BY t1.PriceList_fromDateTimePriceListLedger_PriceListLedger ASC NULLS FIRST,t1.key0 ASC) AS e0
   FROM PriceList_priceListLedger t1
   JOIN
     (SELECT t0.Sale_skuUserInvoiceDetail_UserInvoiceDetail AS k0,
             t0.Sale_dateTimeUserInvoiceDetail_null AS k1,
             t0.Sale_supplierStockUserInvoiceDetail_null AS k2,
             ANYVALUE(1) AS e0
      FROM Sale_userInvoiceDetail t0
      JOIN t_12 t1 ON t1.k0=t0.key0
      WHERE (t0.Sale_skuUserInvoiceDetail_UserInvoiceDetail IS NOT NULL
             AND t0.Sale_dateTimeUserInvoiceDetail_null IS NOT NULL
             AND t0.Sale_supplierStockUserInvoiceDetail_null IS NOT NULL)
      GROUP BY 1,
               2,
               3) t0 ON t0.k0=t1.PriceList_skuPriceListLedger_PriceListLedger
   JOIN PriceList_priceListLedgerLedgerPriceListTypeStock t2 ON t2.key1=452
   AND t2.key2=t0.k2
   AND t2.key0=t1.key0
   LEFT JOIN PriceList_priceListLedgerLedgerPriceListType t3 ON t3.key1=452
   AND t3.key0=t1.key0
   WHERE ((t0.k1>t1.PriceList_fromDateTimePriceListLedger_PriceListLedger)
          AND ((t1.PriceList_toDateTimePriceListLedger_PriceListLedger IS NULL
                OR NOT t0.k1>t1.PriceList_toDateTimePriceListLedger_PriceListLedger))
          AND t2.PriceList_activePriceListLedgerLedgerPriceListTypeStock_null_nu IS NOT NULL
          AND t0.e0 IS NOT NULL)
   GROUP BY 1,
            2,
            3) t1 ON t1.k0=t2.Sale_skuUserInvoiceDetail_UserInvoiceDetail
AND t1.k1=t2.Sale_dateTimeUserInvoiceDetail_null
AND t1.k2=t2.Sale_supplierStockUserInvoiceDetail_null
WHERE ((t0.p0 IS NOT NULL
        OR t1.e0 IS NOT NULL)
       AND t2.Sale_batchUserInvoiceDetail_UserInvoiceDetail IS NULL);



И кстати понял почему в pgAdmin не повторялось. Я когда временную таблицу (t_12) сохранял в постоянную чтобы в pgAdmin запустить, для последней не сделал VACUUM ANALYZE. Тогда postgres думал что записей 1540, а не 327 и план правильный был:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
"Nested Loop Left Join  (cost=92398.54..101478.73 rows=1 width=22) (actual time=0.508..0.508 rows=0 loops=1)"
"  Output: t0.k0, t0.p0"
"  Join Filter: ((t1.pricelist_skupricelistledger_pricelistledger = t2.sale_skuuserinvoicedetail_userinvoicedetail) AND (t0_1.sale_datetimeuserinvoicedetail_null = t2.sale_datetimeuserinvoicedetail_null) AND (t0_1.sale_supplierstockuserinvoicedetail_null =  (...)"
"  Filter: ((t0.p0 IS NOT NULL) OR ((last(t3.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg ORDER BY t1.pricelist_fromdatetimepricelistledger_pricelistledger NULLS FIRST, t1.key0)) IS NOT NULL))"
"  ->  Nested Loop Left Join  (cost=0.42..9072.27 rows=1 width=38) (actual time=0.508..0.508 rows=0 loops=1)"
"        Output: t0.k0, t0.p0, t2.sale_skuuserinvoicedetail_userinvoicedetail, t2.sale_datetimeuserinvoicedetail_null, t2.sale_supplierstockuserinvoicedetail_null"
"        Filter: (t2.sale_batchuserinvoicedetail_userinvoicedetail IS NULL)"
"        Rows Removed by Filter: 327"
"        ->  Seq Scan on public.t_12 t0  (cost=0.00..25.70 rows=1570 width=22) (actual time=0.017..0.034 rows=327 loops=1)"
"              Output: t0.k0, t0.p0"
"        ->  Index Scan using pk_sale_userinvoicedetail on public.sale_userinvoicedetail t2  (cost=0.42..5.75 rows=1 width=24) (actual time=0.001..0.001 rows=1 loops=327)"
"              Output: t2.key0, t2.sale_userinvoiceuserinvoicedetail_userinvoicedetail, t2.sale_quantityuserinvoicedetail_userinvoicedetail, t2.sale_skuuserinvoicedetail_userinvoicedetail, t2.sale_datacustomerstockuserinvoicedetail_userinvoicedetail, t2.sal (...)"
"              Index Cond: (t2.key0 = t0.k0)"
"  ->  GroupAggregate  (cost=92398.12..92405.68 rows=28 width=35) (never executed)"
"        Output: t1.pricelist_skupricelistledger_pricelistledger, t0_1.sale_datetimeuserinvoicedetail_null, t0_1.sale_supplierstockuserinvoicedetail_null, last(t3.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg ORDER BY t1.pricelist_fromdate (...)"
"        ->  Sort  (cost=92398.12..92398.19 rows=28 width=35) (never executed)"
"              Output: t1.pricelist_skupricelistledger_pricelistledger, t0_1.sale_datetimeuserinvoicedetail_null, t0_1.sale_supplierstockuserinvoicedetail_null, t3.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg, t1.pricelist_fromdatetimepri (...)"
"              Sort Key: t1.pricelist_skupricelistledger_pricelistledger, t0_1.sale_datetimeuserinvoicedetail_null, t0_1.sale_supplierstockuserinvoicedetail_null"
"              ->  Nested Loop Left Join  (cost=75723.31..92397.45 rows=28 width=35) (never executed)"
"                    Output: t1.pricelist_skupricelistledger_pricelistledger, t0_1.sale_datetimeuserinvoicedetail_null, t0_1.sale_supplierstockuserinvoicedetail_null, t3.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg, t1.pricelist_fromdatet (...)"
"                    ->  Hash Join  (cost=75722.88..92224.64 rows=28 width=28) (never executed)"
"                          Output: t1.pricelist_skupricelistledger_pricelistledger, t1.pricelist_fromdatetimepricelistledger_pricelistledger, t1.key0, t0_1.sale_datetimeuserinvoicedetail_null, t0_1.sale_supplierstockuserinvoicedetail_null"
"                          Hash Cond: ((t2_1.key2 = t0_1.sale_supplierstockuserinvoicedetail_null) AND (t2_1.key0 = t1.key0))"
"                          ->  Bitmap Heap Scan on public.pricelist_pricelistledgerledgerpricelisttypestock t2_1  (cost=6482.11..20388.41 rows=346024 width=8) (never executed)"
"                                Output: t2_1.key0, t2_1.key1, t2_1.key2, t2_1.pricelist_activepricelistledgerledgerpricelisttypestock_null_nu"
"                                Recheck Cond: (t2_1.key1 = 452)"
"                                Filter: (t2_1.pricelist_activepricelistledgerledgerpricelisttypestock_null_nu IS NOT NULL)"
"                                ->  Bitmap Index Scan on pricelist_pricelistledgerledgerpricelisttypestock_key1_key2_idx  (cost=0.00..6395.61 rows=346024 width=0) (never executed)"
"                                      Index Cond: (t2_1.key1 = 452)"
"                          ->  Hash  (cost=68936.68..68936.68 rows=20272 width=28) (never executed)"
"                                Output: t1.pricelist_skupricelistledger_pricelistledger, t1.pricelist_fromdatetimepricelistledger_pricelistledger, t1.key0, t0_1.sale_datetimeuserinvoicedetail_null, t0_1.sale_supplierstockuserinvoicedetail_null"
"                                ->  Hash Join  (cost=62197.79..68936.68 rows=20272 width=28) (never executed)"
"                                      Output: t1.pricelist_skupricelistledger_pricelistledger, t1.pricelist_fromdatetimepricelistledger_pricelistledger, t1.key0, t0_1.sale_datetimeuserinvoicedetail_null, t0_1.sale_supplierstockuserinvoicedetail_null"
"                                      Hash Cond: (t0_1.sale_skuuserinvoicedetail_userinvoicedetail = t1.pricelist_skupricelistledger_pricelistledger)"
"                                      Join Filter: ((t0_1.sale_datetimeuserinvoicedetail_null > t1.pricelist_fromdatetimepricelistledger_pricelistledger) AND ((t1.pricelist_todatetimepricelistledger_pricelistledger IS NULL) OR (t0_1.sale_datetimeuserinvoic (...)"
"                                      ->  HashAggregate  (cost=9872.98..9888.68 rows=1570 width=16) (never executed)"
"                                            Output: t0_1.sale_skuuserinvoicedetail_userinvoicedetail, t0_1.sale_datetimeuserinvoicedetail_null, t0_1.sale_supplierstockuserinvoicedetail_null, anyvalue(1)"
"                                            Filter: (anyvalue(1) IS NOT NULL)"
"                                            ->  Nested Loop  (cost=0.42..9076.20 rows=1570 width=16) (never executed)"
"                                                  Output: t0_1.sale_skuuserinvoicedetail_userinvoicedetail, t0_1.sale_datetimeuserinvoicedetail_null, t0_1.sale_supplierstockuserinvoicedetail_null"
"                                                  ->  Seq Scan on public.t_12 t1_1  (cost=0.00..25.70 rows=1570 width=4) (never executed)"
"                                                        Output: t1_1.k0, t1_1.p0"
"                                                  ->  Index Scan using pk_sale_userinvoicedetail on public.sale_userinvoicedetail t0_1  (cost=0.42..5.75 rows=1 width=20) (never executed)"
"                                                        Output: t0_1.key0, t0_1.sale_userinvoiceuserinvoicedetail_userinvoicedetail, t0_1.sale_quantityuserinvoicedetail_userinvoicedetail, t0_1.sale_skuuserinvoicedetail_userinvoicedetail, t0_1.sale_datacust (...)"
"                                                        Index Cond: (t0_1.key0 = t1_1.k0)"
"                                                        Filter: ((t0_1.sale_skuuserinvoicedetail_userinvoicedetail IS NOT NULL) AND (t0_1.sale_datetimeuserinvoicedetail_null IS NOT NULL) AND (t0_1.sale_supplierstockuserinvoicedetail_null IS NOT NULL))"
"                                      ->  Hash  (cost=36739.92..36739.92 rows=1246792 width=24) (never executed)"
"                                            Output: t1.pricelist_skupricelistledger_pricelistledger, t1.pricelist_fromdatetimepricelistledger_pricelistledger, t1.key0, t1.pricelist_todatetimepricelistledger_pricelistledger"
"                                            ->  Seq Scan on public.pricelist_pricelistledger t1  (cost=0.00..36739.92 rows=1246792 width=24) (never executed)"
"                                                  Output: t1.pricelist_skupricelistledger_pricelistledger, t1.pricelist_fromdatetimepricelistledger_pricelistledger, t1.key0, t1.pricelist_todatetimepricelistledger_pricelistledger"
"                    ->  Index Scan using pk_pricelist_pricelistledgerledgerpricelisttype on public.pricelist_pricelistledgerledgerpricelisttype t3  (cost=0.43..6.16 rows=1 width=11) (never executed)"
"                          Output: t3.key0, t3.key1, t3.pricelist_inpricelistledgersystemledgerpricelisttype_pricelistl, t3.pricelist_inpricelistledgerledgerpricelisttype_pricelistledger_, t3.pricelist_pricepricelistledgersystemledgerpricelisttype_priceli,  (...)"
"                          Index Cond: ((t3.key0 = t1.key0) AND (t3.key1 = 452))"
"Total runtime: 0.716 ms"



Сделал VACUUM ANALYZE для этой t_12 и план стал :
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
"Nested Loop Left Join  (cost=50107.10..50690.34 rows=1 width=10) (actual time=56442.064..56442.064 rows=0 loops=1)"
"  Output: t0.k0, t0.p0"
"  Filter: (((t0.p0 IS NOT NULL) OR ((last(t3.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg ORDER BY t1.pricelist_fromdatetimepricelistledger_pricelistledger NULLS FIRST, t1.key0)) IS NOT NULL)) AND (t2.sale_batchuserinvoicedetail_userinvo (...)"
"  Rows Removed by Filter: 327"
"  ->  Seq Scan on public.t_12 t0  (cost=0.00..5.27 rows=327 width=10) (actual time=0.004..0.255 rows=327 loops=1)"
"        Output: t0.k0, t0.p0"
"  ->  Hash Right Join  (cost=50107.10..50108.85 rows=1 width=40) (actual time=172.189..172.581 rows=1 loops=327)"
"        Output: t2.key0, t2.sale_batchuserinvoicedetail_userinvoicedetail, (last(t3.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg ORDER BY t1.pricelist_fromdatetimepricelistledger_pricelistledger NULLS FIRST, t1.key0))"
"        Hash Cond: ((t1.pricelist_skupricelistledger_pricelistledger = t2.sale_skuuserinvoicedetail_userinvoicedetail) AND (t0_1.sale_datetimeuserinvoicedetail_null = t2.sale_datetimeuserinvoicedetail_null) AND (t0_1.sale_supplierstockuserinvoicedetail_nul (...)"
"        ->  GroupAggregate  (cost=50099.52..50101.14 rows=6 width=35) (actual time=171.638..172.528 rows=322 loops=327)"
"              Output: t1.pricelist_skupricelistledger_pricelistledger, t0_1.sale_datetimeuserinvoicedetail_null, t0_1.sale_supplierstockuserinvoicedetail_null, last(t3.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg ORDER BY t1.pricelist_fr (...)"
"              ->  Sort  (cost=50099.52..50099.54 rows=6 width=35) (actual time=171.599..171.613 rows=557 loops=327)"
"                    Output: t1.pricelist_skupricelistledger_pricelistledger, t0_1.sale_datetimeuserinvoicedetail_null, t0_1.sale_supplierstockuserinvoicedetail_null, t3.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg, t1.pricelist_fromdatet (...)"
"                    Sort Key: t1.pricelist_skupricelistledger_pricelistledger, t0_1.sale_datetimeuserinvoicedetail_null, t0_1.sale_supplierstockuserinvoicedetail_null"
"                    Sort Method: quicksort  Memory: 68kB"
"                    ->  Nested Loop Left Join  (cost=33561.30..50099.45 rows=6 width=35) (actual time=21.949..171.428 rows=557 loops=327)"
"                          Output: t1.pricelist_skupricelistledger_pricelistledger, t0_1.sale_datetimeuserinvoicedetail_null, t0_1.sale_supplierstockuserinvoicedetail_null, t3.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg, t1.pricelist_fro (...)"
"                          ->  Hash Join  (cost=33560.87..50062.41 rows=6 width=28) (actual time=21.936..170.151 rows=557 loops=327)"
"                                Output: t1.pricelist_skupricelistledger_pricelistledger, t1.pricelist_fromdatetimepricelistledger_pricelistledger, t1.key0, t0_1.sale_datetimeuserinvoicedetail_null, t0_1.sale_supplierstockuserinvoicedetail_null"
"                                Hash Cond: ((t2_1.key2 = t0_1.sale_supplierstockuserinvoicedetail_null) AND (t2_1.key0 = t1.key0))"
"                                ->  Bitmap Heap Scan on public.pricelist_pricelistledgerledgerpricelisttypestock t2_1  (cost=6482.11..20388.41 rows=346024 width=8) (actual time=13.324..42.777 rows=346794 loops=327)"
"                                      Output: t2_1.key0, t2_1.key1, t2_1.key2, t2_1.pricelist_activepricelistledgerledgerpricelisttypestock_null_nu"
"                                      Recheck Cond: (t2_1.key1 = 452)"
"                                      Filter: (t2_1.pricelist_activepricelistledgerledgerpricelisttypestock_null_nu IS NOT NULL)"
"                                      ->  Bitmap Index Scan on pricelist_pricelistledgerledgerpricelisttypestock_key1_key2_idx  (cost=0.00..6395.61 rows=346024 width=0) (actual time=13.112..13.112 rows=346794 loops=327)"
"                                            Index Cond: (t2_1.key1 = 452)"
"                                ->  Hash  (cost=27015.43..27015.43 rows=4222 width=28) (actual time=26.120..26.120 rows=27765 loops=1)"
"                                      Output: t1.pricelist_skupricelistledger_pricelistledger, t1.pricelist_fromdatetimepricelistledger_pricelistledger, t1.key0, t0_1.sale_datetimeuserinvoicedetail_null, t0_1.sale_supplierstockuserinvoicedetail_null"
"                                      Buckets: 1024  Batches: 1  Memory Usage: 1844kB"
"                                      ->  Nested Loop  (cost=2646.80..27015.43 rows=4222 width=28) (actual time=0.644..21.293 rows=27765 loops=1)"
"                                            Output: t1.pricelist_skupricelistledger_pricelistledger, t1.pricelist_fromdatetimepricelistledger_pricelistledger, t1.key0, t0_1.sale_datetimeuserinvoicedetail_null, t0_1.sale_supplierstockuserinvoicedetail_null"
"                                            ->  HashAggregate  (cost=2646.37..2649.64 rows=327 width=16) (actual time=0.636..0.719 rows=322 loops=1)"
"                                                  Output: t0_1.sale_skuuserinvoicedetail_userinvoicedetail, t0_1.sale_datetimeuserinvoicedetail_null, t0_1.sale_supplierstockuserinvoicedetail_null, anyvalue(1)"
"                                                  Filter: (anyvalue(1) IS NOT NULL)"
"                                                  ->  Nested Loop  (cost=0.42..2480.42 rows=327 width=16) (actual time=0.013..0.485 rows=327 loops=1)"
"                                                        Output: t0_1.sale_skuuserinvoicedetail_userinvoicedetail, t0_1.sale_datetimeuserinvoicedetail_null, t0_1.sale_supplierstockuserinvoicedetail_null"
"                                                        ->  Seq Scan on public.t_12 t1_1  (cost=0.00..5.27 rows=327 width=4) (actual time=0.004..0.015 rows=327 loops=1)"
"                                                              Output: t1_1.k0, t1_1.p0"
"                                                        ->  Index Scan using pk_sale_userinvoicedetail on public.sale_userinvoicedetail t0_1  (cost=0.42..7.56 rows=1 width=20) (actual time=0.001..0.001 rows=1 loops=327)"
"                                                              Output: t0_1.key0, t0_1.sale_userinvoiceuserinvoicedetail_userinvoicedetail, t0_1.sale_quantityuserinvoicedetail_userinvoicedetail, t0_1.sale_skuuserinvoicedetail_userinvoicedetail, t0_1.sale_da (...)"
"                                                              Index Cond: (t0_1.key0 = t1_1.k0)"
"                                                              Filter: ((t0_1.sale_skuuserinvoicedetail_userinvoicedetail IS NOT NULL) AND (t0_1.sale_datetimeuserinvoicedetail_null IS NOT NULL) AND (t0_1.sale_supplierstockuserinvoicedetail_null IS NOT NULL) (...)"
"                                            ->  Index Scan using pricelist_pricelistledger_pricelist_skupricelistledger_pricelis on public.pricelist_pricelistledger t1  (cost=0.43..74.37 rows=13 width=24) (actual time=0.003..0.055 rows=86 loops=322)"
"                                                  Output: t1.key0, t1.pricelist_skupricelistledger_pricelistledger, t1.pricelist_ispostedpricelistledger_pricelistledger, t1.pricelist_todatetimepricelistledger_pricelistledger, t1.pricelist_fromdatetimeprice (...)"
"                                                  Index Cond: (t1.pricelist_skupricelistledger_pricelistledger = t0_1.sale_skuuserinvoicedetail_userinvoicedetail)"
"                                                  Filter: ((t0_1.sale_datetimeuserinvoicedetail_null > t1.pricelist_fromdatetimepricelistledger_pricelistledger) AND ((t1.pricelist_todatetimepricelistledger_pricelistledger IS NULL) OR (t0_1.sale_datetimeuse (...)"
"                                                  Rows Removed by Filter: 7"
"                          ->  Index Scan using pk_pricelist_pricelistledgerledgerpricelisttype on public.pricelist_pricelistledgerledgerpricelisttype t3  (cost=0.43..6.16 rows=1 width=11) (actual time=0.002..0.002 rows=1 loops=182139)"
"                                Output: t3.key0, t3.key1, t3.pricelist_inpricelistledgersystemledgerpricelisttype_pricelistl, t3.pricelist_inpricelistledgerledgerpricelisttype_pricelistledger_, t3.pricelist_pricepricelistledgersystemledgerpricelisttype_pri (...)"
"                                Index Cond: ((t3.key0 = t1.key0) AND (t3.key1 = 452))"
"        ->  Hash  (cost=7.56..7.56 rows=1 width=24) (actual time=0.009..0.009 rows=1 loops=327)"
"              Output: t2.key0, t2.sale_skuuserinvoicedetail_userinvoicedetail, t2.sale_datetimeuserinvoicedetail_null, t2.sale_supplierstockuserinvoicedetail_null, t2.sale_batchuserinvoicedetail_userinvoicedetail"
"              Buckets: 1024  Batches: 1  Memory Usage: 1kB"
"              ->  Index Scan using pk_sale_userinvoicedetail on public.sale_userinvoicedetail t2  (cost=0.42..7.56 rows=1 width=24) (actual time=0.007..0.007 rows=1 loops=327)"
"                    Output: t2.key0, t2.sale_skuuserinvoicedetail_userinvoicedetail, t2.sale_datetimeuserinvoicedetail_null, t2.sale_supplierstockuserinvoicedetail_null, t2.sale_batchuserinvoicedetail_userinvoicedetail"
"                    Index Cond: (t2.key0 = t0.k0)"
"Total runtime: 56442.649 ms"
...
Рейтинг: 0 / 0
NESTED LOOP и GroupAggregate
    #38883100
Nitro_Junkie
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nitro_Junkie,

Хм... Помогает уменьшение join_collapse_limit до 2:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
"Nested Loop Left Join  (cost=52695.12..55176.09 rows=1 width=10) (actual time=0.609..0.609 rows=0 loops=1)"
"  Join Filter: ((t1.pricelist_skupricelistledger_pricelistledger = t2.sale_skuuserinvoicedetail_userinvoicedetail) AND (t0_1.sale_datetimeuserinvoicedetail_null = t2.sale_datetimeuserinvoicedetail_null) AND (t0_1.sale_supplierstockuserinvoicedetail_null =  (...)"
"  Filter: ((t0.p0 IS NOT NULL) OR ((last(t3.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg ORDER BY t1.pricelist_fromdatetimepricelistledger_pricelistledger NULLS FIRST, t1.key0)) IS NOT NULL))"
"  ->  Nested Loop Left Join  (cost=0.42..2479.60 rows=1 width=26) (actual time=0.607..0.607 rows=0 loops=1)"
"        Filter: (t2.sale_batchuserinvoicedetail_userinvoicedetail IS NULL)"
"        Rows Removed by Filter: 327"
"        ->  Seq Scan on t_12 t0  (cost=0.00..5.27 rows=327 width=10) (actual time=0.020..0.044 rows=327 loops=1)"
"        ->  Index Scan using pk_sale_userinvoicedetail on sale_userinvoicedetail t2  (cost=0.42..7.56 rows=1 width=24) (actual time=0.001..0.001 rows=1 loops=327)"
"              Index Cond: (key0 = t0.k0)"
"  ->  GroupAggregate  (cost=52694.70..52696.32 rows=6 width=35) (never executed)"
"        ->  Sort  (cost=52694.70..52694.72 rows=6 width=35) (never executed)"
"              Sort Key: t1.pricelist_skupricelistledger_pricelistledger, t0_1.sale_datetimeuserinvoicedetail_null, t0_1.sale_supplierstockuserinvoicedetail_null"
"              ->  Nested Loop Left Join  (cost=33561.30..52694.63 rows=6 width=35) (never executed)"
"                    ->  Hash Join  (cost=33560.87..52657.59 rows=6 width=28) (never executed)"
"                          Hash Cond: ((t2_1.key2 = t0_1.sale_supplierstockuserinvoicedetail_null) AND (t2_1.key0 = t1.key0))"
"                          ->  Bitmap Heap Scan on pricelist_pricelistledgerledgerpricelisttypestock t2_1  (cost=6482.11..20388.41 rows=346024 width=8) (never executed)"
"                                Recheck Cond: (key1 = 452)"
"                                Filter: (pricelist_activepricelistledgerledgerpricelisttypestock_null_nu IS NOT NULL)"
"                                ->  Bitmap Index Scan on pricelist_pricelistledgerledgerpricelisttypestock_key1_key2_idx  (cost=0.00..6395.61 rows=346024 width=0) (never executed)"
"                                      Index Cond: (key1 = 452)"
"                          ->  Hash  (cost=27015.43..27015.43 rows=4222 width=28) (never executed)"
"                                ->  Nested Loop  (cost=2646.80..27015.43 rows=4222 width=28) (never executed)"
"                                      ->  HashAggregate  (cost=2646.37..2649.64 rows=327 width=16) (never executed)"
"                                            Filter: (anyvalue(1) IS NOT NULL)"
"                                            ->  Nested Loop  (cost=0.42..2480.42 rows=327 width=16) (never executed)"
"                                                  ->  Seq Scan on t_12 t1_1  (cost=0.00..5.27 rows=327 width=4) (never executed)"
"                                                  ->  Index Scan using pk_sale_userinvoicedetail on sale_userinvoicedetail t0_1  (cost=0.42..7.56 rows=1 width=20) (never executed)"
"                                                        Index Cond: (key0 = t1_1.k0)"
"                                                        Filter: ((sale_skuuserinvoicedetail_userinvoicedetail IS NOT NULL) AND (sale_datetimeuserinvoicedetail_null IS NOT NULL) AND (sale_supplierstockuserinvoicedetail_null IS NOT NULL))"
"                                      ->  Index Scan using pricelist_pricelistledger_pricelist_skupricelistledger_pricelis on pricelist_pricelistledger t1  (cost=0.43..74.37 rows=13 width=24) (never executed)"
"                                            Index Cond: (pricelist_skupricelistledger_pricelistledger = t0_1.sale_skuuserinvoicedetail_userinvoicedetail)"
"                                            Filter: ((t0_1.sale_datetimeuserinvoicedetail_null > pricelist_fromdatetimepricelistledger_pricelistledger) AND ((pricelist_todatetimepricelistledger_pricelistledger IS NULL) OR (t0_1.sale_datetimeuserinvoicedeta (...)"
"                    ->  Index Scan using pk_pricelist_pricelistledgerledgerpricelisttype on pricelist_pricelistledgerledgerpricelisttype t3  (cost=0.43..6.16 rows=1 width=11) (never executed)"
"                          Index Cond: ((key0 = t1.key0) AND (key1 = 452))"
"Total runtime: 0.806 ms"
...
Рейтинг: 0 / 0
NESTED LOOP и GroupAggregate
    #38883118
Nitro_Junkie
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хотя в общем-то логично что помогает, но управлять порядком join'ов мягко говоря не хочется.

И в принципе если взглянуть на 2 плана то у неэффективного cost ниже. Что очень странно с учетом того что она знает что ей нужно 327 loops сделать, и почему-то cost GroupAggregate'а она не умножает на 327 :(
...
Рейтинг: 0 / 0
NESTED LOOP и GroupAggregate
    #38883131
Nitro_Junkie
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nitro_Junkie,

В общем похоже придется CTE делать, но у меня возникла тогда такая мысль. Ведь она CTE считает до выполнения запроса, а можно заставить ее рассчитать статистику по этому CTE ? Потому как подзапросы основное где postgresql ошибается со статистикой...
...
Рейтинг: 0 / 0
NESTED LOOP и GroupAggregate
    #38883132
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nitro_Junkie,

327 повторов уже заложены в cost
-> GroupAggregate (cost=50099.52..50101.14 rows=6 width=35) (actual time=171.638..172.528 rows=322 loops=327)"
насколько я понимаю.

Разница в планах в том что
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
"  ->  Nested Loop Left Join  (cost=0.42..9072.27 rows=1 width=38) (actual time=0.508..0.508 rows=0 loops=1)"
"        Output: t0.k0, t0.p0, t2.sale_skuuserinvoicedetail_userinvoicedetail, t2.sale_datetimeuserinvoicedetail_null, t2.sale_supplierstockuserinvoicedetail_null"
"        Filter: (t2.sale_batchuserinvoicedetail_userinvoicedetail IS NULL)"
"        Rows Removed by Filter: 327"
"        ->  Seq Scan on public.t_12 t0  (cost=0.00..25.70 rows=1570 width=22) (actual time=0.017..0.034 rows=327 loops=1)"
"              Output: t0.k0, t0.p0"
"        ->  Index Scan using pk_sale_userinvoicedetail on public.sale_userinvoicedetail t2  (cost=0.42..5.75 rows=1 width=24) (actual time=0.001..0.001 rows=1 loops=327)"
"              Output: t2.key0, t2.sale_userinvoiceuserinvoicedetail_userinvoicedetail, t2.sale_quantityuserinvoicedetail_userinvoicedetail, t2.sale_skuuserinvoicedetail_userinvoicedetail, t2.sale_datacustomerstockuserinvoicedetail_userinvoicedetail, t2.sal (...)"
"              Index Cond: (t2.key0 = t0.k0)"

вместо rows=0 получится rows=1 - медленный план станет более быстрым...
а в такой ситуации сложно ожидать стабильного поведения планировщика.

--Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
NESTED LOOP и GroupAggregate
    #38883151
Nitro_Junkie
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim BogukNitro_Junkie,

327 повторов уже заложены в cost
-> GroupAggregate (cost=50099.52..50101.14 rows=6 width=35) (actual time=171.638..172.528 rows=322 loops=327)"
насколько я понимаю.

Разница в планах в том что
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
"  ->  Nested Loop Left Join  (cost=0.42..9072.27 rows=1 width=38) (actual time=0.508..0.508 rows=0 loops=1)"
"        Output: t0.k0, t0.p0, t2.sale_skuuserinvoicedetail_userinvoicedetail, t2.sale_datetimeuserinvoicedetail_null, t2.sale_supplierstockuserinvoicedetail_null"
"        Filter: (t2.sale_batchuserinvoicedetail_userinvoicedetail IS NULL)"
"        Rows Removed by Filter: 327"
"        ->  Seq Scan on public.t_12 t0  (cost=0.00..25.70 rows=1570 width=22) (actual time=0.017..0.034 rows=327 loops=1)"
"              Output: t0.k0, t0.p0"
"        ->  Index Scan using pk_sale_userinvoicedetail on public.sale_userinvoicedetail t2  (cost=0.42..5.75 rows=1 width=24) (actual time=0.001..0.001 rows=1 loops=327)"
"              Output: t2.key0, t2.sale_userinvoiceuserinvoicedetail_userinvoicedetail, t2.sale_quantityuserinvoicedetail_userinvoicedetail, t2.sale_skuuserinvoicedetail_userinvoicedetail, t2.sale_datacustomerstockuserinvoicedetail_userinvoicedetail, t2.sal (...)"
"              Index Cond: (t2.key0 = t0.k0)"

вместо rows=0 получится rows=1 - медленный план станет более быстрым...
а в такой ситуации сложно ожидать стабильного поведения планировщика.

--Maxim Boguk
www.postgresql-consulting.ru

Убрал условие c batchUserInvoiceDetail:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
"Nested Loop Left Join  (cost=50107.10..50690.34 rows=327 width=10) (actual time=188.439..55881.938 rows=327 loops=1)"
"  Filter: ((t0.p0 IS NOT NULL) OR ((last(t3.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg ORDER BY t1.pricelist_fromdatetimepricelistledger_pricelistledger NULLS FIRST, t1.key0)) IS NOT NULL))"
"  ->  Seq Scan on t_12 t0  (cost=0.00..5.27 rows=327 width=10) (actual time=0.004..0.202 rows=327 loops=1)"
"  ->  Hash Right Join  (cost=50107.10..50108.85 rows=1 width=36) (actual time=170.482..170.871 rows=1 loops=327)"
"        Hash Cond: ((t1.pricelist_skupricelistledger_pricelistledger = t2.sale_skuuserinvoicedetail_userinvoicedetail) AND (t0_1.sale_datetimeuserinvoicedetail_null = t2.sale_datetimeuserinvoicedetail_null) AND (t0_1.sale_supplierstockuserinvoicedetail_nul (...)"
"        ->  GroupAggregate  (cost=50099.52..50101.14 rows=6 width=35) (actual time=169.935..170.821 rows=322 loops=327)"
"              ->  Sort  (cost=50099.52..50099.54 rows=6 width=35) (actual time=169.899..169.913 rows=557 loops=327)"
"                    Sort Key: t1.pricelist_skupricelistledger_pricelistledger, t0_1.sale_datetimeuserinvoicedetail_null, t0_1.sale_supplierstockuserinvoicedetail_null"
"                    Sort Method: quicksort  Memory: 68kB"
"                    ->  Nested Loop Left Join  (cost=33561.30..50099.45 rows=6 width=35) (actual time=21.529..169.737 rows=557 loops=327)"
"                          ->  Hash Join  (cost=33560.87..50062.41 rows=6 width=28) (actual time=21.518..168.511 rows=557 loops=327)"
"                                Hash Cond: ((t2_1.key2 = t0_1.sale_supplierstockuserinvoicedetail_null) AND (t2_1.key0 = t1.key0))"
"                                ->  Bitmap Heap Scan on pricelist_pricelistledgerledgerpricelisttypestock t2_1  (cost=6482.11..20388.41 rows=346024 width=8) (actual time=13.090..42.030 rows=346794 loops=327)"
"                                      Recheck Cond: (key1 = 452)"
"                                      Filter: (pricelist_activepricelistledgerledgerpricelisttypestock_null_nu IS NOT NULL)"
"                                      ->  Bitmap Index Scan on pricelist_pricelistledgerledgerpricelisttypestock_key1_key2_idx  (cost=0.00..6395.61 rows=346024 width=0) (actual time=12.882..12.882 rows=346794 loops=327)"
"                                            Index Cond: (key1 = 452)"
"                                ->  Hash  (cost=27015.43..27015.43 rows=4222 width=28) (actual time=21.796..21.796 rows=27765 loops=1)"
"                                      Buckets: 1024  Batches: 1  Memory Usage: 1844kB"
"                                      ->  Nested Loop  (cost=2646.80..27015.43 rows=4222 width=28) (actual time=0.638..17.482 rows=27765 loops=1)"
"                                            ->  HashAggregate  (cost=2646.37..2649.64 rows=327 width=16) (actual time=0.630..0.705 rows=322 loops=1)"
"                                                  Filter: (anyvalue(1) IS NOT NULL)"
"                                                  ->  Nested Loop  (cost=0.42..2480.42 rows=327 width=16) (actual time=0.016..0.484 rows=327 loops=1)"
"                                                        ->  Seq Scan on t_12 t1_1  (cost=0.00..5.27 rows=327 width=4) (actual time=0.005..0.018 rows=327 loops=1)"
"                                                        ->  Index Scan using pk_sale_userinvoicedetail on sale_userinvoicedetail t0_1  (cost=0.42..7.56 rows=1 width=20) (actual time=0.001..0.001 rows=1 loops=327)"
"                                                              Index Cond: (key0 = t1_1.k0)"
"                                                              Filter: ((sale_skuuserinvoicedetail_userinvoicedetail IS NOT NULL) AND (sale_datetimeuserinvoicedetail_null IS NOT NULL) AND (sale_supplierstockuserinvoicedetail_null IS NOT NULL))"
"                                            ->  Index Scan using pricelist_pricelistledger_pricelist_skupricelistledger_pricelis on pricelist_pricelistledger t1  (cost=0.43..74.37 rows=13 width=24) (actual time=0.003..0.044 rows=86 loops=322)"
"                                                  Index Cond: (pricelist_skupricelistledger_pricelistledger = t0_1.sale_skuuserinvoicedetail_userinvoicedetail)"
"                                                  Filter: ((t0_1.sale_datetimeuserinvoicedetail_null > pricelist_fromdatetimepricelistledger_pricelistledger) AND ((pricelist_todatetimepricelistledger_pricelistledger IS NULL) OR (t0_1.sale_datetimeuserinvoi (...)"
"                                                  Rows Removed by Filter: 7"
"                          ->  Index Scan using pk_pricelist_pricelistledgerledgerpricelisttype on pricelist_pricelistledgerledgerpricelisttype t3  (cost=0.43..6.16 rows=1 width=11) (actual time=0.002..0.002 rows=1 loops=182139)"
"                                Index Cond: ((key0 = t1.key0) AND (key1 = 452))"
"        ->  Hash  (cost=7.56..7.56 rows=1 width=20) (actual time=0.008..0.008 rows=1 loops=327)"
"              Buckets: 1024  Batches: 1  Memory Usage: 1kB"
"              ->  Index Scan using pk_sale_userinvoicedetail on sale_userinvoicedetail t2  (cost=0.42..7.56 rows=1 width=20) (actual time=0.006..0.006 rows=1 loops=327)"
"                    Index Cond: (key0 = t0.k0)"
"Total runtime: 55882.539 ms"



Хороший план с join_collapse 2:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
"Hash Left Join  (cost=52696.91..55179.78 rows=327 width=10) (actual time=200.904..201.951 rows=327 loops=1)"
"  Hash Cond: ((t2.sale_skuuserinvoicedetail_userinvoicedetail = t1.pricelist_skupricelistledger_pricelistledger) AND (t2.sale_datetimeuserinvoicedetail_null = t0_1.sale_datetimeuserinvoicedetail_null) AND (t2.sale_supplierstockuserinvoicedetail_null = t0_1 (...)"
"  Filter: ((t0.p0 IS NOT NULL) OR ((last(t3.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg ORDER BY t1.pricelist_fromdatetimepricelistledger_pricelistledger NULLS FIRST, t1.key0)) IS NOT NULL))"
"  ->  Nested Loop Left Join  (cost=0.42..2479.60 rows=327 width=26) (actual time=0.018..0.862 rows=327 loops=1)"
"        ->  Seq Scan on t_12 t0  (cost=0.00..5.27 rows=327 width=10) (actual time=0.007..0.045 rows=327 loops=1)"
"        ->  Index Scan using pk_sale_userinvoicedetail on sale_userinvoicedetail t2  (cost=0.42..7.56 rows=1 width=20) (actual time=0.002..0.002 rows=1 loops=327)"
"              Index Cond: (key0 = t0.k0)"
"  ->  Hash  (cost=52696.38..52696.38 rows=6 width=48) (actual time=200.865..200.865 rows=322 loops=1)"
"        Buckets: 1024  Batches: 1  Memory Usage: 19kB"
"        ->  GroupAggregate  (cost=52694.70..52696.32 rows=6 width=35) (actual time=199.694..200.784 rows=322 loops=1)"
"              ->  Sort  (cost=52694.70..52694.72 rows=6 width=35) (actual time=199.583..199.597 rows=557 loops=1)"
"                    Sort Key: t1.pricelist_skupricelistledger_pricelistledger, t0_1.sale_datetimeuserinvoicedetail_null, t0_1.sale_supplierstockuserinvoicedetail_null"
"                    Sort Method: quicksort  Memory: 68kB"
"                    ->  Nested Loop Left Join  (cost=33561.30..52694.63 rows=6 width=35) (actual time=47.585..199.289 rows=557 loops=1)"
"                          ->  Hash Join  (cost=33560.87..52657.59 rows=6 width=28) (actual time=47.577..197.840 rows=557 loops=1)"
"                                Hash Cond: ((t2_1.key2 = t0_1.sale_supplierstockuserinvoicedetail_null) AND (t2_1.key0 = t1.key0))"
"                                ->  Bitmap Heap Scan on pricelist_pricelistledgerledgerpricelisttypestock t2_1  (cost=6482.11..20388.41 rows=346024 width=8) (actual time=13.771..44.395 rows=346794 loops=1)"
"                                      Recheck Cond: (key1 = 452)"
"                                      Filter: (pricelist_activepricelistledgerledgerpricelisttypestock_null_nu IS NOT NULL)"
"                                      ->  Bitmap Index Scan on pricelist_pricelistledgerledgerpricelisttypestock_key1_key2_idx  (cost=0.00..6395.61 rows=346024 width=0) (actual time=13.545..13.545 rows=346794 loops=1)"
"                                            Index Cond: (key1 = 452)"
"                                ->  Hash  (cost=27015.43..27015.43 rows=4222 width=28) (actual time=23.701..23.701 rows=27765 loops=1)"
"                                      Buckets: 1024  Batches: 1  Memory Usage: 1844kB"
"                                      ->  Nested Loop  (cost=2646.80..27015.43 rows=4222 width=28) (actual time=1.268..19.032 rows=27765 loops=1)"
"                                            ->  HashAggregate  (cost=2646.37..2649.64 rows=327 width=16) (actual time=1.231..1.326 rows=322 loops=1)"
"                                                  Filter: (anyvalue(1) IS NOT NULL)"
"                                                  ->  Nested Loop  (cost=0.42..2480.42 rows=327 width=16) (actual time=0.056..0.784 rows=327 loops=1)"
"                                                        ->  Seq Scan on t_12 t1_1  (cost=0.00..5.27 rows=327 width=4) (actual time=0.026..0.050 rows=327 loops=1)"
"                                                        ->  Index Scan using pk_sale_userinvoicedetail on sale_userinvoicedetail t0_1  (cost=0.42..7.56 rows=1 width=20) (actual time=0.002..0.002 rows=1 loops=327)"
"                                                              Index Cond: (key0 = t1_1.k0)"
"                                                              Filter: ((sale_skuuserinvoicedetail_userinvoicedetail IS NOT NULL) AND (sale_datetimeuserinvoicedetail_null IS NOT NULL) AND (sale_supplierstockuserinvoicedetail_null IS NOT NULL))"
"                                            ->  Index Scan using pricelist_pricelistledger_pricelist_skupricelistledger_pricelis on pricelist_pricelistledger t1  (cost=0.43..74.37 rows=13 width=24) (actual time=0.003..0.047 rows=86 loops=322)"
"                                                  Index Cond: (pricelist_skupricelistledger_pricelistledger = t0_1.sale_skuuserinvoicedetail_userinvoicedetail)"
"                                                  Filter: ((t0_1.sale_datetimeuserinvoicedetail_null > pricelist_fromdatetimepricelistledger_pricelistledger) AND ((pricelist_todatetimepricelistledger_pricelistledger IS NULL) OR (t0_1.sale_datetimeuserinvoi (...)"
"                                                  Rows Removed by Filter: 7"
"                          ->  Index Scan using pk_pricelist_pricelistledgerledgerpricelisttype on pricelist_pricelistledgerledgerpricelisttype t3  (cost=0.43..6.16 rows=1 width=11) (actual time=0.002..0.002 rows=1 loops=557)"
"                                Index Cond: ((key0 = t1.key0) AND (key1 = 452))"
"Total runtime: 202.558 ms"
...
Рейтинг: 0 / 0
NESTED LOOP и GroupAggregate
    #38883163
Nitro_Junkie
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk327 повторов уже заложены в cost
-> GroupAggregate (cost=50099.52..50101.14 rows=6 width=35) (actual time=171.638..172.528 rows=322 loops=327)"
насколько я понимаю.


Сделала с CTE:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
"Hash Left Join  (cost=52696.97..55179.84 rows=327 width=10) (actual time=201.614..202.159 rows=327 loops=1)"
"  Hash Cond: ((t2.sale_skuuserinvoicedetail_userinvoicedetail = t1.k0) AND (t2.sale_datetimeuserinvoicedetail_null = t1.k1) AND (t2.sale_supplierstockuserinvoicedetail_null = t1.k2))"
"  Filter: ((t0.p0 IS NOT NULL) OR (t1.e0 IS NOT NULL))"
"  CTE sq1"
"    ->  GroupAggregate  (cost=52694.70..52696.32 rows=6 width=35) (actual time=200.412..201.436 rows=322 loops=1)"
"          ->  Sort  (cost=52694.70..52694.72 rows=6 width=35) (actual time=200.313..200.329 rows=557 loops=1)"
"                Sort Key: t1_1.pricelist_skupricelistledger_pricelistledger, t0_1.sale_datetimeuserinvoicedetail_null, t0_1.sale_supplierstockuserinvoicedetail_null"
"                Sort Method: quicksort  Memory: 68kB"
"                ->  Nested Loop Left Join  (cost=33561.30..52694.63 rows=6 width=35) (actual time=49.339..200.046 rows=557 loops=1)"
"                      ->  Hash Join  (cost=33560.87..52657.59 rows=6 width=28) (actual time=49.331..198.826 rows=557 loops=1)"
"                            Hash Cond: ((t2_1.key2 = t0_1.sale_supplierstockuserinvoicedetail_null) AND (t2_1.key0 = t1_1.key0))"
"                            ->  Bitmap Heap Scan on pricelist_pricelistledgerledgerpricelisttypestock t2_1  (cost=6482.11..20388.41 rows=346024 width=8) (actual time=13.994..43.968 rows=346794 loops=1)"
"                                  Recheck Cond: (key1 = 452)"
"                                  Filter: (pricelist_activepricelistledgerledgerpricelisttypestock_null_nu IS NOT NULL)"
"                                  ->  Bitmap Index Scan on pricelist_pricelistledgerledgerpricelisttypestock_key1_key2_idx  (cost=0.00..6395.61 rows=346024 width=0) (actual time=13.787..13.787 rows=346794 loops=1)"
"                                        Index Cond: (key1 = 452)"
"                            ->  Hash  (cost=27015.43..27015.43 rows=4222 width=28) (actual time=25.791..25.791 rows=27765 loops=1)"
"                                  Buckets: 1024  Batches: 1  Memory Usage: 1844kB"
"                                  ->  Nested Loop  (cost=2646.80..27015.43 rows=4222 width=28) (actual time=0.634..20.987 rows=27765 loops=1)"
"                                        ->  HashAggregate  (cost=2646.37..2649.64 rows=327 width=16) (actual time=0.626..0.722 rows=322 loops=1)"
"                                              Filter: (anyvalue(1) IS NOT NULL)"
"                                              ->  Nested Loop  (cost=0.42..2480.42 rows=327 width=16) (actual time=0.013..0.473 rows=327 loops=1)"
"                                                    ->  Seq Scan on t_12 t1_2  (cost=0.00..5.27 rows=327 width=4) (actual time=0.004..0.016 rows=327 loops=1)"
"                                                    ->  Index Scan using pk_sale_userinvoicedetail on sale_userinvoicedetail t0_1  (cost=0.42..7.56 rows=1 width=20) (actual time=0.001..0.001 rows=1 loops=327)"
"                                                          Index Cond: (key0 = t1_2.k0)"
"                                                          Filter: ((sale_skuuserinvoicedetail_userinvoicedetail IS NOT NULL) AND (sale_datetimeuserinvoicedetail_null IS NOT NULL) AND (sale_supplierstockuserinvoicedetail_null IS NOT NULL))"
"                                        ->  Index Scan using pricelist_pricelistledger_pricelist_skupricelistledger_pricelis on pricelist_pricelistledger t1_1  (cost=0.43..74.37 rows=13 width=24) (actual time=0.004..0.054 rows=86 loops=322)"
"                                              Index Cond: (pricelist_skupricelistledger_pricelistledger = t0_1.sale_skuuserinvoicedetail_userinvoicedetail)"
"                                              Filter: ((t0_1.sale_datetimeuserinvoicedetail_null > pricelist_fromdatetimepricelistledger_pricelistledger) AND ((pricelist_todatetimepricelistledger_pricelistledger IS NULL) OR (t0_1.sale_datetimeuserinvoicede (...)"
"                                              Rows Removed by Filter: 7"
"                      ->  Index Scan using pk_pricelist_pricelistledgerledgerpricelisttype on pricelist_pricelistledgerledgerpricelisttype t3  (cost=0.43..6.16 rows=1 width=11) (actual time=0.002..0.002 rows=1 loops=557)"
"                            Index Cond: ((key0 = t1_1.key0) AND (key1 = 452))"
"  ->  Nested Loop Left Join  (cost=0.42..2479.60 rows=327 width=26) (actual time=0.010..0.472 rows=327 loops=1)"
"        ->  Seq Scan on t_12 t0  (cost=0.00..5.27 rows=327 width=10) (actual time=0.004..0.018 rows=327 loops=1)"
"        ->  Index Scan using pk_sale_userinvoicedetail on sale_userinvoicedetail t2  (cost=0.42..7.56 rows=1 width=20) (actual time=0.001..0.001 rows=1 loops=327)"
"              Index Cond: (key0 = t0.k0)"
"  ->  Hash  (cost=0.12..0.12 rows=6 width=48) (actual time=201.594..201.594 rows=322 loops=1)"
"        Buckets: 1024  Batches: 1  Memory Usage: 19kB"
"        ->  CTE Scan on sq1 t1  (cost=0.00..0.12 rows=6 width=48) (actual time=200.414..201.536 rows=322 loops=1)"
"Total runtime: 202.666 ms"



Cost все равно 50к, так что не уверен что loops в неэффективном плане в него включены.
...
Рейтинг: 0 / 0
NESTED LOOP и GroupAggregate
    #38883232
Фотография vyegorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk327 повторов уже заложены в cost
Код: plaintext
1.
->  GroupAggregate  (cost=50099.52..50101.14 rows=6 width=35) (actual time=171.638..172.528 rows=322 loops=327)"
насколько я понимаю.

Это просто констатация фактически пройденных циклов (вторая скобка). Планировщик использует предполагаемое кол-во записей.

@Nitro_Junkie , а вы могли бы указать версию PostgreSQL и измененную конфигурацию? Статистика свежая на таблицах?
Если они временные, то их надо явно анализировать, т.к. они не видны `autovacuum` демону.
...
Рейтинг: 0 / 0
NESTED LOOP и GroupAggregate
    #38883241
Nitro_Junkie
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vyegorovMaxim Boguk327 повторов уже заложены в cost
Код: plaintext
1.
->  GroupAggregate  (cost=50099.52..50101.14 rows=6 width=35) (actual time=171.638..172.528 rows=322 loops=327)"
насколько я понимаю.

Это просто констатация фактически пройденных циклов (вторая скобка). Планировщик использует предполагаемое кол-во записей.

@Nitro_Junkie , а вы могли бы указать версию PostgreSQL и измененную конфигурацию? Статистика свежая на таблицах?
Если они временные, то их надо явно анализировать, т.к. они не видны `autovacuum` демону.

"PostgreSQL 9.3.4, compiled by Visual C++ build 1600, 64-bit"

Статистика естественно свежая. Более того когда она не свежая, планировщик лучше работает :)
...
Рейтинг: 0 / 0
NESTED LOOP и GroupAggregate
    #38883255
Фотография vyegorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nitro_Junkie,

Ах... Вы используете одни и те же алиасы таблиц в разных частях запроса. Я не уверен, к какой `t0` привязывается планировщик в разных частях запроса:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
SELECT t0.k0 AS jkey0,
       t0.p0 AS jprop0
FROM t_12 t0
LEFT JOIN Sale_userInvoiceDetail t2 ON t2.key0=t0.k0
LEFT JOIN
  (SELECT t1.PriceList_skuPriceListLedger_PriceListLedger AS k0,
          t0.k1 AS k1,
          t0.k2 AS k2,
          LAST(t3.PriceList_pricePriceListLedgerLedgerPriceListType_PriceListLedg
               ORDER BY t1.PriceList_fromDateTimePriceListLedger_PriceListLedger ASC NULLS FIRST,t1.key0 ASC) AS e0
   FROM PriceList_priceListLedger t1
   JOIN
     (SELECT t0.Sale_skuUserInvoiceDetail_UserInvoiceDetail AS k0,
             t0.Sale_dateTimeUserInvoiceDetail_null AS k1,
             t0.Sale_supplierStockUserInvoiceDetail_null AS k2,
             ANYVALUE(1) AS e0
      FROM Sale_userInvoiceDetail t0
      JOIN t_12 t1 ON t1.k0=t0.key0
      WHERE (t0.Sale_skuUserInvoiceDetail_UserInvoiceDetail IS NOT NULL
             AND t0.Sale_dateTimeUserInvoiceDetail_null IS NOT NULL
             AND t0.Sale_supplierStockUserInvoiceDetail_null IS NOT NULL)
      GROUP BY 1,
               2,
               3) t0 ON t0.k0=t1.PriceList_skuPriceListLedger_PriceListLedger
   JOIN PriceList_priceListLedgerLedgerPriceListTypeStock t2 ON t2.key1=452
   AND t2.key2=t0.k2
   AND t2.key0=t1.key0
   LEFT JOIN PriceList_priceListLedgerLedgerPriceListType t3 ON t3.key1=452
   AND t3.key0=t1.key0
   WHERE ((t0.k1>t1.PriceList_fromDateTimePriceListLedger_PriceListLedger)
          AND ((t1.PriceList_toDateTimePriceListLedger_PriceListLedger IS NULL
                OR NOT t0.k1>t1.PriceList_toDateTimePriceListLedger_PriceListLedger))
          AND t2.PriceList_activePriceListLedgerLedgerPriceListTypeStock_null_nu IS NOT NULL
          AND t0.e0 IS NOT NULL)
   GROUP BY 1,
            2,
            3) t1 ON t1.k0=t2.Sale_skuUserInvoiceDetail_UserInvoiceDetail
AND t1.k1=t2.Sale_dateTimeUserInvoiceDetail_null
AND t1.k2=t2.Sale_supplierStockUserInvoiceDetail_null
WHERE ((t0.p0 IS NOT NULL
        OR t1.e0 IS NOT NULL)
       AND t2.Sale_batchUserInvoiceDetail_UserInvoiceDetail IS NULL);


Тот факт, что `join_collapse_limit` помогает, делает меня более уверенным. Попробуйте дать уникальные алиасы.
...
Рейтинг: 0 / 0
NESTED LOOP и GroupAggregate
    #38883256
Nitro_Junkie
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vyegorovNitro_Junkie,

Ах... Вы используете одни и те же алиасы таблиц в разных частях запроса. Я не уверен, к какой `t0` привязывается планировщик в разных частях запроса:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
SELECT t0.k0 AS jkey0,
       t0.p0 AS jprop0
FROM t_12 t0
LEFT JOIN Sale_userInvoiceDetail t2 ON t2.key0=t0.k0
LEFT JOIN
  (SELECT t1.PriceList_skuPriceListLedger_PriceListLedger AS k0,
          t0.k1 AS k1,
          t0.k2 AS k2,
          LAST(t3.PriceList_pricePriceListLedgerLedgerPriceListType_PriceListLedg
               ORDER BY t1.PriceList_fromDateTimePriceListLedger_PriceListLedger ASC NULLS FIRST,t1.key0 ASC) AS e0
   FROM PriceList_priceListLedger t1
   JOIN
     (SELECT t0.Sale_skuUserInvoiceDetail_UserInvoiceDetail AS k0,
             t0.Sale_dateTimeUserInvoiceDetail_null AS k1,
             t0.Sale_supplierStockUserInvoiceDetail_null AS k2,
             ANYVALUE(1) AS e0
      FROM Sale_userInvoiceDetail t0
      JOIN t_12 t1 ON t1.k0=t0.key0
      WHERE (t0.Sale_skuUserInvoiceDetail_UserInvoiceDetail IS NOT NULL
             AND t0.Sale_dateTimeUserInvoiceDetail_null IS NOT NULL
             AND t0.Sale_supplierStockUserInvoiceDetail_null IS NOT NULL)
      GROUP BY 1,
               2,
               3) t0 ON t0.k0=t1.PriceList_skuPriceListLedger_PriceListLedger
   JOIN PriceList_priceListLedgerLedgerPriceListTypeStock t2 ON t2.key1=452
   AND t2.key2=t0.k2
   AND t2.key0=t1.key0
   LEFT JOIN PriceList_priceListLedgerLedgerPriceListType t3 ON t3.key1=452
   AND t3.key0=t1.key0
   WHERE ((t0.k1>t1.PriceList_fromDateTimePriceListLedger_PriceListLedger)
          AND ((t1.PriceList_toDateTimePriceListLedger_PriceListLedger IS NULL
                OR NOT t0.k1>t1.PriceList_toDateTimePriceListLedger_PriceListLedger))
          AND t2.PriceList_activePriceListLedgerLedgerPriceListTypeStock_null_nu IS NOT NULL
          AND t0.e0 IS NOT NULL)
   GROUP BY 1,
            2,
            3) t1 ON t1.k0=t2.Sale_skuUserInvoiceDetail_UserInvoiceDetail
AND t1.k1=t2.Sale_dateTimeUserInvoiceDetail_null
AND t1.k2=t2.Sale_supplierStockUserInvoiceDetail_null
WHERE ((t0.p0 IS NOT NULL
        OR t1.e0 IS NOT NULL)
       AND t2.Sale_batchUserInvoiceDetail_UserInvoiceDetail IS NULL);


Тот факт, что `join_collapse_limit` помогает, делает меня более уверенным. Попробуйте дать уникальные алиасы.

Там в планировщике она подчеркивания добавляет. Но честно попробовал, не помогло естественно.
...
Рейтинг: 0 / 0
NESTED LOOP и GroupAggregate
    #38883261
Фотография vyegorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nitro_JunkievyegorovПопробуйте дать уникальные алиасы.
Там в планировщике она подчеркивания добавляет. Но честно попробовал, не помогло естественно.
А можно увидеть измененный запрос и его планы, с обычными настройками и при `join_collaps_limit=2`?
...
Рейтинг: 0 / 0
NESTED LOOP и GroupAggregate
    #38883575
Nitro_Junkie
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vyegorov,
Запрос:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
SET join_collapse_limit to 8;
EXPLAIN ANALYZE 
SELECT t0.k0 AS jkey0,
       t0.p0 AS jprop0
FROM t_12 t0
LEFT JOIN Sale_userInvoiceDetail t2 ON t2.key0=t0.k0
LEFT JOIN
  (SELECT t18.PriceList_skuPriceListLedger_PriceListLedger AS k0,
          t9.k1 AS k1,
          t9.k2 AS k2,
          LAST(t3.PriceList_pricePriceListLedgerLedgerPriceListType_PriceListLedg
               ORDER BY t18.PriceList_fromDateTimePriceListLedger_PriceListLedger ASC NULLS FIRST,t18.key0 ASC) AS e0
   FROM PriceList_priceListLedger t18
   JOIN
     (SELECT t7.Sale_skuUserInvoiceDetail_UserInvoiceDetail AS k0,
             t7.Sale_dateTimeUserInvoiceDetail_null AS k1,
             t7.Sale_supplierStockUserInvoiceDetail_null AS k2,
             ANYVALUE(1) AS e0
      FROM Sale_userInvoiceDetail t7
      JOIN t_12 t19 ON t19.k0=t7.key0
      WHERE (t7.Sale_skuUserInvoiceDetail_UserInvoiceDetail IS NOT NULL
             AND t7.Sale_dateTimeUserInvoiceDetail_null IS NOT NULL
             AND t7.Sale_supplierStockUserInvoiceDetail_null IS NOT NULL)
      GROUP BY 1,
               2,
               3) t9 ON t9.k0=t18.PriceList_skuPriceListLedger_PriceListLedger
   JOIN PriceList_priceListLedgerLedgerPriceListTypeStock t20 ON t20.key1=452
   AND t20.key2=t9.k2
   AND t20.key0=t18.key0
   LEFT JOIN PriceList_priceListLedgerLedgerPriceListType t3 ON t3.key1=452
   AND t3.key0=t18.key0
   WHERE ((t9.k1>t18.PriceList_fromDateTimePriceListLedger_PriceListLedger)
          AND ((t18.PriceList_toDateTimePriceListLedger_PriceListLedger IS NULL
                OR NOT t9.k1>t18.PriceList_toDateTimePriceListLedger_PriceListLedger))
          AND t20.PriceList_activePriceListLedgerLedgerPriceListTypeStock_null_nu IS NOT NULL
          AND t9.e0 IS NOT NULL)
   GROUP BY 1,
            2,
            3) t1 ON t1.k0=t2.Sale_skuUserInvoiceDetail_UserInvoiceDetail
AND t1.k1=t2.Sale_dateTimeUserInvoiceDetail_null
AND t1.k2=t2.Sale_supplierStockUserInvoiceDetail_null
WHERE ((t0.p0 IS NOT NULL
        OR t1.e0 IS NOT NULL)
       );



Кривой план:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
"Nested Loop Left Join  (cost=50107.10..50690.34 rows=327 width=10) (actual time=197.691..60609.058 rows=327 loops=1)"
"  Filter: ((t0.p0 IS NOT NULL) OR ((last(t3.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg ORDER BY t18.pricelist_fromdatetimepricelistledger_pricelistledger NULLS FIRST, t18.key0)) IS NOT NULL))"
"  ->  Seq Scan on t_12 t0  (cost=0.00..5.27 rows=327 width=10) (actual time=0.006..0.260 rows=327 loops=1)"
"  ->  Hash Right Join  (cost=50107.10..50108.85 rows=1 width=36) (actual time=184.927..185.323 rows=1 loops=327)"
"        Hash Cond: ((t18.pricelist_skupricelistledger_pricelistledger = t2.sale_skuuserinvoicedetail_userinvoicedetail) AND (t7.sale_datetimeuserinvoicedetail_null = t2.sale_datetimeuserinvoicedetail_null) AND (t7.sale_supplierstockuserinvoicedetail_null = (...)"
"        ->  GroupAggregate  (cost=50099.52..50101.14 rows=6 width=35) (actual time=184.359..185.268 rows=322 loops=327)"
"              ->  Sort  (cost=50099.52..50099.54 rows=6 width=35) (actual time=184.319..184.333 rows=557 loops=327)"
"                    Sort Key: t18.pricelist_skupricelistledger_pricelistledger, t7.sale_datetimeuserinvoicedetail_null, t7.sale_supplierstockuserinvoicedetail_null"
"                    Sort Method: quicksort  Memory: 68kB"
"                    ->  Nested Loop Left Join  (cost=33561.30..50099.45 rows=6 width=35) (actual time=23.581..184.131 rows=557 loops=327)"
"                          ->  Hash Join  (cost=33560.87..50062.41 rows=6 width=28) (actual time=23.566..182.733 rows=557 loops=327)"
"                                Hash Cond: ((t20.key2 = t7.sale_supplierstockuserinvoicedetail_null) AND (t20.key0 = t18.key0))"
"                                ->  Bitmap Heap Scan on pricelist_pricelistledgerledgerpricelisttypestock t20  (cost=6482.11..20388.41 rows=346024 width=8) (actual time=13.812..44.815 rows=346794 loops=327)"
"                                      Recheck Cond: (key1 = 452)"
"                                      Filter: (pricelist_activepricelistledgerledgerpricelisttypestock_null_nu IS NOT NULL)"
"                                      ->  Bitmap Index Scan on pricelist_pricelistledgerledgerpricelisttypestock_key1_key2_idx  (cost=0.00..6395.61 rows=346024 width=0) (actual time=13.597..13.597 rows=346794 loops=327)"
"                                            Index Cond: (key1 = 452)"
"                                ->  Hash  (cost=27015.43..27015.43 rows=4222 width=28) (actual time=24.290..24.290 rows=27765 loops=1)"
"                                      Buckets: 1024  Batches: 1  Memory Usage: 1844kB"
"                                      ->  Nested Loop  (cost=2646.80..27015.43 rows=4222 width=28) (actual time=0.938..20.240 rows=27765 loops=1)"
"                                            ->  HashAggregate  (cost=2646.37..2649.64 rows=327 width=16) (actual time=0.925..1.010 rows=322 loops=1)"
"                                                  Filter: (anyvalue(1) IS NOT NULL)"
"                                                  ->  Nested Loop  (cost=0.42..2480.42 rows=327 width=16) (actual time=0.017..0.593 rows=327 loops=1)"
"                                                        ->  Seq Scan on t_12 t19  (cost=0.00..5.27 rows=327 width=4) (actual time=0.004..0.024 rows=327 loops=1)"
"                                                        ->  Index Scan using pk_sale_userinvoicedetail on sale_userinvoicedetail t7  (cost=0.42..7.56 rows=1 width=20) (actual time=0.001..0.001 rows=1 loops=327)"
"                                                              Index Cond: (key0 = t19.k0)"
"                                                              Filter: ((sale_skuuserinvoicedetail_userinvoicedetail IS NOT NULL) AND (sale_datetimeuserinvoicedetail_null IS NOT NULL) AND (sale_supplierstockuserinvoicedetail_null IS NOT NULL))"
"                                            ->  Index Scan using pricelist_pricelistledger_pricelist_skupricelistledger_pricelis on pricelist_pricelistledger t18  (cost=0.43..74.37 rows=13 width=24) (actual time=0.003..0.050 rows=86 loops=322)"
"                                                  Index Cond: (pricelist_skupricelistledger_pricelistledger = t7.sale_skuuserinvoicedetail_userinvoicedetail)"
"                                                  Filter: ((t7.sale_datetimeuserinvoicedetail_null > pricelist_fromdatetimepricelistledger_pricelistledger) AND ((pricelist_todatetimepricelistledger_pricelistledger IS NULL) OR (t7.sale_datetimeuserinvoicede (...)"
"                                                  Rows Removed by Filter: 7"
"                          ->  Index Scan using pk_pricelist_pricelistledgerledgerpricelisttype on pricelist_pricelistledgerledgerpricelisttype t3  (cost=0.43..6.16 rows=1 width=11) (actual time=0.002..0.002 rows=1 loops=182139)"
"                                Index Cond: ((key0 = t18.key0) AND (key1 = 452))"
"        ->  Hash  (cost=7.56..7.56 rows=1 width=20) (actual time=0.010..0.010 rows=1 loops=327)"
"              Buckets: 1024  Batches: 1  Memory Usage: 1kB"
"              ->  Index Scan using pk_sale_userinvoicedetail on sale_userinvoicedetail t2  (cost=0.42..7.56 rows=1 width=20) (actual time=0.008..0.008 rows=1 loops=327)"
"                    Index Cond: (key0 = t0.k0)"
"Total runtime: 60609.709 ms"



Нормальный план (с join_collapse 2):
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
"Hash Left Join  (cost=52696.91..55179.78 rows=327 width=10) (actual time=205.813..206.362 rows=327 loops=1)"
"  Hash Cond: ((t2.sale_skuuserinvoicedetail_userinvoicedetail = t18.pricelist_skupricelistledger_pricelistledger) AND (t2.sale_datetimeuserinvoicedetail_null = t7.sale_datetimeuserinvoicedetail_null) AND (t2.sale_supplierstockuserinvoicedetail_null = t7.sa (...)"
"  Filter: ((t0.p0 IS NOT NULL) OR ((last(t3.pricelist_pricepricelistledgerledgerpricelisttype_pricelistledg ORDER BY t18.pricelist_fromdatetimepricelistledger_pricelistledger NULLS FIRST, t18.key0)) IS NOT NULL))"
"  ->  Nested Loop Left Join  (cost=0.42..2479.60 rows=327 width=26) (actual time=0.010..0.474 rows=327 loops=1)"
"        ->  Seq Scan on t_12 t0  (cost=0.00..5.27 rows=327 width=10) (actual time=0.004..0.016 rows=327 loops=1)"
"        ->  Index Scan using pk_sale_userinvoicedetail on sale_userinvoicedetail t2  (cost=0.42..7.56 rows=1 width=20) (actual time=0.001..0.001 rows=1 loops=327)"
"              Index Cond: (key0 = t0.k0)"
"  ->  Hash  (cost=52696.38..52696.38 rows=6 width=48) (actual time=205.773..205.773 rows=322 loops=1)"
"        Buckets: 1024  Batches: 1  Memory Usage: 19kB"
"        ->  GroupAggregate  (cost=52694.70..52696.32 rows=6 width=35) (actual time=204.687..205.722 rows=322 loops=1)"
"              ->  Sort  (cost=52694.70..52694.72 rows=6 width=35) (actual time=204.614..204.627 rows=557 loops=1)"
"                    Sort Key: t18.pricelist_skupricelistledger_pricelistledger, t7.sale_datetimeuserinvoicedetail_null, t7.sale_supplierstockuserinvoicedetail_null"
"                    Sort Method: quicksort  Memory: 68kB"
"                    ->  Nested Loop Left Join  (cost=33561.30..52694.63 rows=6 width=35) (actual time=46.469..204.378 rows=557 loops=1)"
"                          ->  Hash Join  (cost=33560.87..52657.59 rows=6 width=28) (actual time=46.458..202.873 rows=557 loops=1)"
"                                Hash Cond: ((t20.key2 = t7.sale_supplierstockuserinvoicedetail_null) AND (t20.key0 = t18.key0))"
"                                ->  Bitmap Heap Scan on pricelist_pricelistledgerledgerpricelisttypestock t20  (cost=6482.11..20388.41 rows=346024 width=8) (actual time=14.208..45.028 rows=346794 loops=1)"
"                                      Recheck Cond: (key1 = 452)"
"                                      Filter: (pricelist_activepricelistledgerledgerpricelisttypestock_null_nu IS NOT NULL)"
"                                      ->  Bitmap Index Scan on pricelist_pricelistledgerledgerpricelisttypestock_key1_key2_idx  (cost=0.00..6395.61 rows=346024 width=0) (actual time=13.932..13.932 rows=346794 loops=1)"
"                                            Index Cond: (key1 = 452)"
"                                ->  Hash  (cost=27015.43..27015.43 rows=4222 width=28) (actual time=24.424..24.424 rows=27765 loops=1)"
"                                      Buckets: 1024  Batches: 1  Memory Usage: 1844kB"
"                                      ->  Nested Loop  (cost=2646.80..27015.43 rows=4222 width=28) (actual time=0.673..19.207 rows=27765 loops=1)"
"                                            ->  HashAggregate  (cost=2646.37..2649.64 rows=327 width=16) (actual time=0.665..0.752 rows=322 loops=1)"
"                                                  Filter: (anyvalue(1) IS NOT NULL)"
"                                                  ->  Nested Loop  (cost=0.42..2480.42 rows=327 width=16) (actual time=0.013..0.478 rows=327 loops=1)"
"                                                        ->  Seq Scan on t_12 t19  (cost=0.00..5.27 rows=327 width=4) (actual time=0.004..0.015 rows=327 loops=1)"
"                                                        ->  Index Scan using pk_sale_userinvoicedetail on sale_userinvoicedetail t7  (cost=0.42..7.56 rows=1 width=20) (actual time=0.001..0.001 rows=1 loops=327)"
"                                                              Index Cond: (key0 = t19.k0)"
"                                                              Filter: ((sale_skuuserinvoicedetail_userinvoicedetail IS NOT NULL) AND (sale_datetimeuserinvoicedetail_null IS NOT NULL) AND (sale_supplierstockuserinvoicedetail_null IS NOT NULL))"
"                                            ->  Index Scan using pricelist_pricelistledger_pricelist_skupricelistledger_pricelis on pricelist_pricelistledger t18  (cost=0.43..74.37 rows=13 width=24) (actual time=0.003..0.048 rows=86 loops=322)"
"                                                  Index Cond: (pricelist_skupricelistledger_pricelistledger = t7.sale_skuuserinvoicedetail_userinvoicedetail)"
"                                                  Filter: ((t7.sale_datetimeuserinvoicedetail_null > pricelist_fromdatetimepricelistledger_pricelistledger) AND ((pricelist_todatetimepricelistledger_pricelistledger IS NULL) OR (t7.sale_datetimeuserinvoicede (...)"
"                                                  Rows Removed by Filter: 7"
"                          ->  Index Scan using pk_pricelist_pricelistledgerledgerpricelisttype on pricelist_pricelistledgerledgerpricelisttype t3  (cost=0.43..6.16 rows=1 width=11) (actual time=0.002..0.002 rows=1 loops=557)"
"                                Index Cond: ((key0 = t18.key0) AND (key1 = 452))"
"Total runtime: 206.888 ms"
...
Рейтинг: 0 / 0
NESTED LOOP и GroupAggregate
    #38883785
Фотография vyegorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nitro_Junkie,

Интерсная картинка. При `jcl=2` планировщик увеличивает цену подзапросу `t1` и предпочитает HashJoin, что приводит к нужному эффекту. Почему так происходит понять не могу, в остальном планы одинаковые.

Что возвращают такие запросы?
Код: sql
1.
2.
SELECT name,setting,source FROM pg_settings WHERE name ~ 'cost' AND NOT name ~ 'vacuum';
SELECT name,setting,source FROM pg_settings WHERE NOT source IN ('default','override');



Вы можете смоделировать ситуацию на другой базе? Скажем, если дампнуть таблицы, создать новый кластер, загрузить таблицы, проанализировать их — какой будет план?
...
Рейтинг: 0 / 0
NESTED LOOP и GroupAggregate
    #38883788
Alexius
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nitro_Junkie,

оторвать бы кому-нибудь руки за такие имена таблиц и полей.
...
Рейтинг: 0 / 0
NESTED LOOP и GroupAggregate
    #38883817
Nitro_Junkie
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vyegorov,

"cpu_index_tuple_cost";"0.005";"default"
"cpu_operator_cost";"0.0025";"default"
"cpu_tuple_cost";"0.01";"default"
"random_page_cost";"4";"default"
"seq_page_cost";"1";"default"

"application_name";"pgAdmin III - ???????????????????? ????????????????";"client"
"bytea_output";"escape";"session"
"client_encoding";"UNICODE";"session"
"client_min_messages";"notice";"session"
"DateStyle";"ISO, DMY";"session"
"default_text_search_config";"pg_catalog.russian";"configuration file"
"lc_messages";"Russian_Russia.1251";"configuration file"
"lc_monetary";"Russian_Russia.1251";"configuration file"
"lc_numeric";"Russian_Russia.1251";"configuration file"
"lc_time";"Russian_Russia.1251";"configuration file"
"listen_addresses";"*";"configuration file"
"log_destination";"stderr";"configuration file"
"log_line_prefix";"%t ";"configuration file"
"log_timezone";"Europe/Bucharest";"configuration file"
"logging_collector";"on";"configuration file"
"max_connections";"100";"configuration file"
"max_locks_per_transaction";"1000";"configuration file"
"max_stack_depth";"2048";"environment variable"
"port";"5432";"configuration file"
"shared_buffers";"16384";"configuration file"
"TimeZone";"Europe/Bucharest";"configuration file"
"work_mem";"524288";"configuration file"

Сча попробую dump restore. Но меня в принципе волнует вопрос почему при подсчете cost'а плана, СУБД не учитывает что при Nested Loop нужно несколько раз выполнять GroupAggregate.
...
Рейтинг: 0 / 0
NESTED LOOP и GroupAggregate
    #38883826
Фотография vyegorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nitro_Junkie,

Да, я понимаю про NestedLoops.
Если вы сможете изолированно воспроизвести ситуацию, то можно написать разработчикам (я могу помочь).
...
Рейтинг: 0 / 0
NESTED LOOP и GroupAggregate
    #38883850
Nitro_Junkie
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vyegorovNitro_Junkie,

Да, я понимаю про NestedLoops.
Если вы сможете изолированно воспроизвести ситуацию, то можно написать разработчикам (я могу помочь).

Изолировать постараюсь в любом случае, и если он будет тривиальным запостить багрепорт, но пока мы прорабатываем вопрос решения проблемы в общем случае - самим материализовать подзапросы, если "что-то пошло не так". Можно конечно через CTE это делать, но там статистика плывет.

Просто разработчики конечно может и помогут, но вряд ли они изменят, то что когда планировщик про Aggregate чего-то не знает, тупо лепит ему статистику 200, после чего начинаются чудеса с nested loop'ами. Плюс проблему надо решать уже :(
...
Рейтинг: 0 / 0
25 сообщений из 40, страница 1 из 2
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / NESTED LOOP и GroupAggregate
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]