sql >> Database >  >> RDS >> Mysql

dure query haalt databaseserver uit -- op zoek naar manieren om dit te verminderen

Hmm, ik zou kunnen proberen om je vraag als volgt te schrijven:

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 

Verschillende kolommen verplaatst voor organisatorische doeleinden. Dit zou geen groot effect moeten hebben op de verwerkingstijd.

Ik heb de verwijzing naar phppos_suppliers verwijderd als:

  1. U gebruikt geen kolommen uit de tabel
  2. Het is een LEFT JOIN , wat betekent dat je geen rijen nodig hebt om daar te bestaan.

Ik heb de GROUP BY . verplaatst in een nieuwe subquery, omdat phppos_sales_item_taxes is de enige tabel die dubbele rijen kan hebben voor de opgegeven criteria. Ik heb de verwijzing naar phppos_sales toegevoegd omdat ik niet zeker weet of MySQL's optimizer (of een andere, echt) slim genoeg is om citeria naar beneden te duwen.

Het grootste deel van de query is verplaatst naar een subquery, zodat ik de formule voor lineSubtotal niet hoef te typen meerdere keren. Ik heb overal dezelfde formules gebruikt, maar er zijn vereenvoudigde versies beschikbaar:

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

.... misschien moet u deze echter boekhoudkundig uitvoeren, omdat ze (begrijpelijkerwijs) gevoelig zijn voor de volgorde van bewerkingen. Dit mag resulteren in een snellere runtime, maar ik betwijfel het; meestal gaat dit over vereenvoudiging van de termen tot iets leesbaars.

Je hebt geen tabellay-outs gegeven voor de andere helft van de query, maar ik neem aan dat het vergelijkbaar is. De gerelateerde wijziging wordt overgelaten als een oefening voor de lezer.

Algemene mitigatiestrategieën

Afgezien van de mogelijke versnelling van het wijzigen van de zoekopdracht, zijn er een aantal dingen die u kunt doen om het probleem te beperken:

  1. Dwing deze query (en mogelijk andere) in uw applicatielaag om een ​​taakverzendingsproces te doorlopen waarvan de resultaten later kunnen worden opgehaald. Een nieuwe kopie van deze query kan pas worden uitgevoerd als de vorige is voltooid. Ik neem aan dat php hiervoor een bestaande bibliotheek heeft. Gewoon afknijpen van de inzending in het algemeen is misschien alles wat je nodig hebt.
  2. De gegevens die worden opgehaald lijken vatbaar voor caching - sla alles op vóór de meest recent verwerkte sale_date , en krijg dan alleen on-the-fly nieuwe informatie (hoewel de transformatie niet echt zo verschillend is van het origineel - het kan echter helpen om gewoon niet meer mee te doen).
  3. Sta query's over de huidige verwerkingstijd niet toe. Dit zou moeten voorkomen dat het systeem toegang probeert te krijgen tot rijen die nog niet zijn vastgelegd, en mogelijk weg van indexpagina's die worden gewijzigd. Dit soort trucjes werkt het beste als je opslagruimte is ingericht om te profiteren van gelijktijdige I/O.



  1. Hoe duplicaten te vinden in 2 kolommen, niet in 1

  2. Nullen naar links opvullen in postgreSQL

  3. Verbruikt MySQL aanzienlijk meer bronnen in vergelijking met andere DBMS?

  4. SQL-instructie - SQL-matrix