PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Как да опростите заявка за избор, която съдържа много вътрешни селекти и да увеличите производителността в PostgreSQL

Оптимизации :

  1. Получаване на всички изчисления на агрегати в едно избиране - групиране по заявка.
  2. Замяна на подизбрани с ляво съединение
  3. Допълнително ограничение във вътрешна заявка въз основа на външни условия.

Вземете това като такова:

with gtab4_5 as (
    select 
        gtab04.Productid, gtab05.BatchId
    FROM
       gtab04 
    LEFT JOIN gtab05 
        ON gtab04.Productid = gtab05.Productid  
    WHERE (gtab04.Masked = False AND gtab04.Banned = false)  
        AND  gtab04.patentid in  (321, 313 , 267 , 431) 
)
  SELECT 
   gtab04.Productid,
   gtab04.Product,
   gtab04.SaleUnit ,
   gtab04.Packing,
   gtab04.ConvFact,
   gtab04.PTR,
   gtab04.MRP, 
   gtab04.PRate,
   gtab04.PTR1,
   gtab04.PTR2,
   gtab04.Location,
   0 As ManufId,
   gtab07.PatentId,
   gtab07.Patent,
   gtab07.PatentCd,
   gtab15.TaxId,
   gtab15.TaxName, 
   gtab15.TaxType,
   gtab15.TaxRate, 
   gtab15.TxOMRP,
   ''::text As Manufacture,
   stats_ags.StkEntered AS StkEntered,
   stats_ags.OpeningInQty as OpeningInQty,
   stats_ags.OpeningOutQty as OpeningOutQty,
   0 AS PurchQty, 
   0 AS SRetQty, 
   0 AS PerInQty, 
   0 AS SaleQty, 
   0 AS StockInQty,
   0 AS StockOutQty, 
   0 AS SaleAmt, 
   0 AS DamageQty, 
   0 AS PRetQty, 
   0 AS PerOutQty,
   stats_ags.PrMthSaleQty as PrMthSaleQty,
   stats_ags.PrMthSaleAmt as PrMthSaleAmt,
   gtab04.LandCost,
   gtab05.PTR AS BatchPTR,
      (case when (
      gtab05.Fqty -  gtab05.FIQty)>0 then (gtab05.Fqty -  gtab05.FIQty) else 0 end) as 
   IssdFreeQty, 
   gtab05.MRP AS BatchMRP, 
   gtab05.PRate AS BatchPRate, 
   gtab04.StdPack,  
      (date_part('day',  (Select Min(Expiry) From gtab05 WHERE  gtab05.Productid =    
      gtab04.Productid And gtab05.Qty > gtab05.IQty)-Cast('2014-06-20' AS    
      timestamp))) AS 
   ExpDys, 
   stats_ags.LastSaleDate as LastSaleDate ,
   GTAB05.BatchId, 
   0 AS FreeSaleQty, 
   0 AS ReplSaleQty 
FROM
   gtab04 
INNER JOIN  gtab15 
    ON gtab04.TaxId = gtab15.TaxId  
LEFT JOIN gtab05 
    ON gtab04.Productid = gtab05.Productid   
INNER JOIN gtab07 
    ON gtab07.Patentid = gtab04.Patentid  
left join (
        SELECT gtab10_9.Productid, gtab10_9.BatchId, 
            max( case 
                when gtab10_9.acyrid = 7 
                then gtab10_9.Productid else null 
            end) as StkEntered,
            SUM( case 
                when gtab10_9.acyrid = 7 and ( 
                    gtab10_9.vrid = 6 
                or (
                    gtab10_9.vrid in (10,11,23,42,35) 
                    AND gtab10_9.trdate < Cast('2014-06-01' AS timestamp) 
                ) ) 
                then gtab10_9.qty else 0 
            end) as OpeningInQty,
            SUM( case 
                when gtab10_9.acyrid = 7 
                    and gtab10_9.vrid in( 12,32,33,44 ,45 ,46, 47 ,48 , 49,18 , 34 ,25,27 ,15,26,24 , 43 ,36) 
                    AND gtab10_9.trdate < Cast('2014-06-01'   AS timestamp)                 
                then gtab10_9.qty else 0 
            end) as OpeningOutQty,
            SUM( case 
                when gtab10_9.acyrid = 7 
                    and gtab10_9.vrid in(12 ,32 ,33 ,44 ,45 ,46 ,47,48,49) 
                    AND gtab10_9.trdate BETWEEN '2014-05-01' AND '2014-05-31'               
                then gtab10_9.qty else 0 
            end) as PrMthSaleQty,
            SUM( case 
                when gtab10_9.acyrid = 7 
                    and gtab10_9.vrid in( 12, 32 , 33 , 44 ,45 ,46 , 47,48 , 49) 
                    and (gtab10_9.FreeOrRpl = 0 OR gtab10_9.FreeOrRpl = 2) 
                    AND gtab10_9.trdate BETWEEN '2014-05-01' AND '2014-05-31'               
                then gtab10_9.qty * gtab10_9.ptr else 0 
            end) as PrMthSaleAmt,
            MAX( case 
                when gtab10_9.acyrid = 7 
                    and gtab10_9.VrId in (12,32,33,44,45,46, 47,48,49)
                    and (gtab10_9.FreeOrRpl = 0 OR gtab10_9.FreeOrRpl = 2) 
                then gtab10_9.TrDate else null 
            end) as LastSaleDate
        FROM (
            SELECT gtab10.*, gtab09.*
            FROM gtab10 
            INNER JOIN gtab09 ON gtab09.TranId = gtab10.TranId 
            inner join gtab4_5 on   gtab4_5.Productid = gtab10.Productid and gtab4_5.BatchId = gtab10.BatchId
        ) gtab10_9 
        group by gtab10_9.Productid, gtab10_9.BatchId
    ) stats_ags
    on stats_ags.Productid = gtab04.Productid 
    and stats_ags.BatchId = gtab05.BatchId
WHERE (gtab04.Masked = False AND gtab04.Banned = false)  
    AND  gtab04.patentid in  (321, 313 , 267 , 431) 
ORDER BY Patent, gtab04.Product

Моите резултати с тази заявка:

Sort  (cost=82928.96..82931.84 rows=1152 width=306) (actual time=447.433..450.191 rows=2421 loops=1)
  Sort Key: gtab07.patent, gtab04.product
  Sort Method: external merge  Disk: 680kB

Срещу оригиналния вариант:

Sort  (cost=2796544.62..2796547.50 rows=1152 width=278) (actual time=47865.883..47868.570 rows=2421 loops=1)
  Sort Key: gtab07.patent, gtab04.product
  Sort Method: external merge  Disk: 680kB

Размерът за сортиране и броят на редовете все още са същите, както се предполага, че са...

Измервания въз основа на вашите данни за проби PG 9.3



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да изпълните множество съединения с различни параметри в една заявка

  2. Вертикално мащабиране на PostgreSQL

  3. Случайно премахнати привилегиите на суперпотребител по подразбиране на postgres - мога ли да ги върна?

  4. pgDash Diagnostics Алтернативи - PostgreSQL управление на заявки с ClusterControl

  5. Методът org.postgresql.jdbc4.Jdbc4Connection.isValid(int) все още не е внедрен