sql >> Database >  >> RDS >> PostgreSQL

Hoe een selectiequery die veel inner-selects bevat vereenvoudigen en de prestaties in PostgreSQL verbeteren?

Optimalisaties :

  1. Krijg alle calculaties van alle aggregaties in één selectie - groeperen op zoekopdracht.
  2. Vervang subselecties door left join
  3. Aanvullende beperking in innerlijke zoekopdracht op basis van uiterlijke voorwaarden.

Krijg dit als zodanig:

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

Mijn resultaten met deze zoekopdracht:

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

Vs originele variant:

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

Grootte voor sorteren en rijen tellen nog steeds hetzelfde als verondersteld te zijn...

Metingen op basis van uw monstergegevens PG 9.3



  1. Hoe voeg ik twee of meer rijen samen op basis van hun externe sleutel?

  2. Wat is een 'meerdelige identifier' en waarom kan deze niet worden gebonden?

  3. een SQL-rij hashen?

  4. Kunnen we het aantal rijen in een tabel in MySQL beperken?