我的查询运行缓慢的Mysql

时间:2016-10-06 03:46:54

标签: mysql

SELECT(inv_total - isc_total)AS利润FROM(
SELECT
SUM(inv.net_weight * inv.unit_price)AS isc_total,
SUM(CASE WHEN(i。“。$ ex_gst。”ex_gst ='YES')
那么(inv.net_weight *(CASE WHEN(i.final ='Y'和i.currency_id IS NOT NULL)那么(ind.final_unit_price * cr.currency_value)
                                    WHEN(i.final ='Y'和i.currency_id为NULL)那么ind.final_unit_price
                                    WHEN(i.final<>'Y'和i.currency_id不为空)那么(ind.unit_price * cr.currency_value)
                                    WHEN(i.final<>'Y'和i.currency_id为空)那么ind.unit_price ELSE ind.unit_price END)* 1.06)
                            ELSE(inv.net_weight *(CASE WHEN(i.final ='Y'和i.currency_id IS NOT NULL)那么(ind.final_unit_price * cr.currency_value)
                                    WHEN(i.final ='Y'和i.currency_id为NULL)那么ind.final_unit_price
                                    WHEN(i.final<>'Y'和i.currency_id不为空)那么(ind.unit_price * cr.currency_value)
                                    什么时候(i.final<>'Y'和i.currency_id为空)那么ind.unit_price
                                    ELSE ind.unit_price END)
                            )结束
                        )AS inv_total
FROM“。$ prefix_qry。”inventory inv
                        INNER JOIN“。$ prefix_qry。”osc_detail osc_do ON osc_do.inventory_id = inv.inventory_id
                        INNER JOIN产品p ON inv.product_id = p.product_id
                        LEFT JOIN“。$ prefix_qry。”isc isc ON inv.isc_batch_no = isc.isc_batch_no
                        INNER JOIN供应商的ON isc.supplier_id = s.supplier_id
                        INNER JOIN“。$ prefix_qry。”发票i ON inv.osc_id = i.osc_id
                        INNER JOIN“。$ prefix_qry。”invoice_detail ind ON i.invoice_id = ind.invoice_id AND ind.product_id = p.product_id
                        LEFT JOIN货币cr ON i.currency_id = cr.currency_id
                        WHERE inv.osc_id!=''
                        AND inv.inventory_type ='CONFIRM'
                        AND i.cancel_by IS NULL
                        AND s.supplier_id ='“。$ supp_id。”'
                        和月(i.date_of_delivery)='“。$月。”'
AND YEAR(i.date_of_delivery)='“。$ year。”')AS A

1 个答案:

答案 0 :(得分:0)

允许MySQL在date_of_delivery作为前导列的索引上有效使用范围扫描,假设$ year表示有效年份,$ month是1到12之间的值,则更改为:

     AND MONTH(i.date_of_delivery) = '".$month."'
     AND YEAR(i.date_of_delivery) = '".$year ."'

对于这样的事情:

     AND i.date_of_delivery >= STR_TO_DATE('".$year."-".$month."-01','%Y-%m-%d')
     AND i.date_of_delivery  < STR_TO_DATE('".$year."-".$month."-01','%Y-%m-%d') 
                               + INTERVAL 1 MONTH

&#34;外在&#34; LEFT JOINisc的后续内部联接被s否定。也就是说,将LEFT JOIN替换为INNER JOIN来获得等效结果。

确保合适的索引可用且正在使用中。

EXPLAIN输出将显示执行计划。

除此之外,我们确实需要查看EXPLAIN输出。这将为我们提供有关可用索引,表统计信息等的线索。为了真正深入挖掘,我们需要知道查询中涉及的所有表的所有索引的定义,以及谓词中涉及的列的数据类型。

鉴于内联视图查询返回单行,派生表的开销可以忽略不计。

此查询应返回与原始内联视图等效的结果。

SELECT SUM( inv.net_weight
          * inv.unit_price
       ) AS isc_total
     , SUM( inv.net_weight
          * IF(( i.".$ex_gst."ex_gst = 'YES' ), 1.06, 1.00)
          * IF(( i.final = 'Y' ), ind.final_unit_price, ind.unit_price)
          * IF(( i.final IS NULL OR i.currency_id IS NULL ), 1.00, cr.currency_value)
       ) AS inv_total
  FROM ".$prefix_qry."invoice i
  JOIN ".$prefix_qry."invoice_detail ind
    ON ind.invoice_id       = i.invoice_id
  JOIN ".$prefix_qry."inventory inv
    ON inv.product_id       = ind.product_id
   AND inv.inventory_type   = 'CONFIRM'
   AND inv.osc_id           = i.osc_id
   AND inv.osc_id          != ''
  JOIN ".$prefix_qry."osc_detail osc_do
    ON osc_do.inventory_id  = inv.inventory_id
  JOIN ".$prefix_qry."isc isc
    ON isc.supplier_id      = '".$supp_id."'
   AND isc.isc_batch_no     = inv.isc_batch_no
  JOIN supplier s
    ON s.supplier_id        = '".$supp_id."'
   AND s.supplier_id        = isc.supplier_id
  JOIN product p
    ON p.product_id         = inv.product_id
   AND p.product_id         = ind.product_id
  LEFT
  JOIN currency cr
    ON cr.currency_id       = i.currency_id
 WHERE i.cancel_by         IS NULL
   AND i.osc_id            != ''
   AND i.date_of_delivery  >= DATE_FROM_STR('".$year."-".$month."-01','%Y-%m-%d')
   AND i.date_of_delivery   < DATE_FROM_STR('".$year."-".$month."-01','%Y-%m-%d')
                              + INTERVAL 1 MONTH

SELECT列表中的列用法摘要

-------- ---------------------------------------------------------------
i        final, currency_id, $[ex_gst]ex_gst
inv      net_weight,unit_price
cr       currency_value

PREDICATES中列使用情况摘要

-------- ---------------------------------------------------------------
i        osc_id, invoice_id, cancel_by, date_of_delivery
ind      invoice_id
inv      inventory_id, isc_batch_no, osc_id, inventory_type, product_id
isc      isc_batch_no, supplier_id
osc_do   inventory_id
p        product_id
s        supplier_id
cr       currency_id

可能这些表格较小,并且已将这些列作为PRIMARY KEY

... ON p       (product_id)
... ON s       (supplier_id)
... ON cr      (currency_id)

我们应该考虑是否必要包含productp)和suppliers)表格查询。如果ps使用的列(如上所示)是PRIMARY KEY或UNIQUE KEY,并且强制执行这些外键约束:

 inv (product_id)  references p (product_id)
 ind (product_id)  references p (product_id)
 isc (supplier_id) references s (supplier_id)

然后加入ps不会影响结果。也就是说,可以从查询中删除这些表。

首次覆盖索引可能有助于优化器生成有效的执行计划...

... ON i       (date_of_delivery,cancel_by,osc_id,invoice_id,final,currency_id,[$ex_gst]ex_gst)
... ON ind     (invoice_id, product_id)
... ON inv     (inventory_id,inventory_type,isc_batch_no,osc_id,inventory_type,product_id,net_weight,unit_price)
... ON isc     (supplier_id,isc_batch_no)
... ON osc_do  (inventory_id)