sql >> Databasteknik >  >> RDS >> Mysql

dyr fråga tar ner databasserver -- letar efter sätt att mildra

Hmm, jag kan försöka skriva din fråga på följande sätt:

SELECT Sale_Item.deleted, Sale_Item.deleted_by,
       Sale_Item.sale_time, Sale_Item.sale_date,
       Sale_Item.comment,
       Sale_Item.payment_type,
       Sale_Item.customer_id,
       Sale_Item.employee_id,
       Sale_Item.category,
       Sale_Item.sale_id, Sale_Item.item_id, NULL as item_kit_id, Sale_Item.line, 
       Sale_Item.supplier_id,
       Sale_Item.serialnumber, Sale_Item.description,
       Sale_Item.quantity_purchased, Sale_Item.item_cost_price, Sale_Item.item_unit_price,
       Sale_Item.discount_percent,
       Sale_Item.lineSubtotal,
       Sale_Item.lineSubtotal * COALESCE(Tax.non_cumulative, 0) + (Sale_Item.lineSubtotal * COALESCE(Tax.non_cumulative, 0) + Sale_Item.non_cumulative) * COALESCE(Tax.cumulative, 0) AS lineTax,
       Sale_Item.lineSubtotal + (Sale_Item.lineSubtotal * COALESCE(Tax.non_cumulative, 0) + (Sale_Item.lineSubtotal * COALESCE(Tax.non_cumulative, 0) + Sale_Item.non_cumulative) * COALESCE(Tax.cumulative, 0)) AS lineTotal,
       Sale_Item.lineSubtotal - (Sale_Item.item_cost_price * Sale_Item.quantity_purchased) AS profit

FROM (SELECT Sale.deleted, Sale.deleted_by,
             Sale.sale_time, DATE(Sale.sale_time) AS sale_date,
             Sale.comment,
             Sale.payment_type,
             Sale.customer_id,
             Sale.employee_id,
             Item.category,
             Sale_Item.sale_id, Sale_Item.item_id, NULL as item_kit_id, Sale_Item.line, 
             Sale_Item.supplier_id,
             Sale_Item.serialnumber, Sale_Item.description,
             Sale_Item.quantity_purchased, Sale_Item.item_cost_price, Sale_Item.item_unit_price,
             Sale_Item.discount_percent,
             (Sale_Item.item_unit_price * Sale_Item.quantity_purchased) - (Sale_Item.item_unit_price * Sale_Item.quantity_purchased * Sale_Item.discount_percent / 100) as lineSubtotal                 
      FROM phppos_sales_items Sale_Item
      JOIN phppos_sales Sale
        ON Sale.sale_id = Sale_Item.sale_id
           AND Sale.sale_time >= TIMESTAMP('2014-04-01')
           AND Sale.sale_time < TIMESTAMPADD(MONTH, 1, '2014-04-01')
           AND Sale.location_id = 1
           AND Sale.store_account_payment = 0) Sale_Item

LEFT JOIN (SELECT Tax.sale_id, Tax.item_id, Tax.line,
                  SUM(CASE WHEN Tax.cumulative = 1 THEN Tax.percent ELSE 0 END) as cumulative,
                  SUM(CASE WHEN Tax.cumulative <> 1 THEN Tax.percent ELSE 0 END) as non_cumulative
           FROM phppos_sales_item_taxes Tax
           JOIN phppos_sales Sale
             ON Sale.sale_id = Tax.sale_id
                AND Sale.sale_time >= TIMESTAMP('2014-04-01')
                AND Sale.sale_time < TIMESTAMPADD(MONTH, 1, '2014-04-01')
                AND Sale.location_id = 1
                AND Sale.store_account_payment = 0
           GROUP BY Tax.sale_id, Tax.item_id, Tax.line) Tax
       ON Tax.sale_id = Sale_Item.sale_id
          AND Tax.item_id = Sale_Item.sale_id
          AND Tax.line =Sale_Item.line 

Flyttade flera kolumner i organisatoriska syften. Detta bör inte ha någon större effekt på handläggningstiden.

Jag tog bort referensen till phppos_suppliers som:

  1. Du använder inga kolumner från tabellen
  2. Det är en LEFT JOIN , vilket betyder att du inte kräver att rader finns där.

Jag flyttade GROUP BY till en ny underfråga, eftersom phppos_sales_item_taxes är den enda tabellen som kan ha dubbletter av rader för de givna kriterierna. Jag inkluderade referensen till phppos_sales eftersom jag inte är säker på om MySQL:s optimerare (eller någon, verkligen) är smart nog att trycka ner citeria.

Huvuddelen av frågan har flyttats till en underfråga helt enkelt så att jag inte skulle behöva skriva formeln för lineSubtotal flera gånger. Jag har använt samma formler genomgående, men det finns förenklade versioner tillgängliga:

Sale_Item.item_unit_price * Sale_Item.quantity_purchased * (1 - (Sale_Item.discount_percent / 100)) as lineSubtotal  

Sale_Item.lineSubtotal * COALESCE(Tax.non_cumulative + Tax.cumulative + Tax.non_cumulative * Tax.cumulative, 0) as Tax

.... du kanske måste köra dessa genom bokföring, eftersom de tenderar att vara (förståeligt nog) känsliga för ordningsföljden. Detta kan resultera i en snabbare körtid men jag tvivlar på det; mest handlar det om att förenkla termerna till något mer läsbart.

Du angav inga tabelllayouter för den andra hälften av frågan, men jag antar att den är liknande. Den relaterade modifieringen lämnas som en övning för läsaren.

Allmänna begränsningsstrategier

Utöver eventuella snabbare förändringar av frågan, finns det ett antal saker du kan göra för att minska problemet:

  1. Tvinga den här frågan (och eventuellt andra) i ditt ansökningslager att gå igenom en process för inlämning av jobb vars resultat kan hämtas senare. En ny kopia av den här frågan kan inte köras förrän den föregående är klar. Jag antar att php har ett befintligt bibliotek för detta. Att bara strypa inlämning i allmänhet kan vara allt du behöver.
  2. Datan som hämtas verkar vara tillgänglig för cachning - lagra allt före det senast bearbetade sale_date , och sedan bara få ny information i farten (även om transformationen egentligen inte är så annorlunda från originalet - dock kan det hjälpa att helt enkelt inte göra fler joins).
  3. Tillåt inte frågor under den aktuella bearbetningstiden. Detta bör hindra systemet från att försöka få åtkomst till rader som inte har registrerats ännu, och eventuellt borta från indexsidor under modifiering. Den här typen av knep fungerar bäst om din lagring är utformad för att dra fördel av samtidiga I/O.



  1. Hur skriver man största n per grupp typ fråga, men med ytterligare villkor?

  2. 6 funktioner för att hämta dag, månad och år från ett datum i SQL Server

  3. Det går inte att installera mysqlclient på centos

  4. Hur får man fram kolumnnamnen på tabellen i en databas i zend?