【问题标题】:How to optimize my MySQL query?如何优化我的 MySQL 查询?
【发布时间】:2012-10-08 18:57:25
【问题描述】:

我有两张桌子 发票( Id, Status, VendorId, CustomerId, OrderDate, InvoiceFor, )

发票项目( Id, Status, InvoiceId, ProductId, PackageQty, PackagePrice, )

这里 invoice.id=invoiceItem.invoiceId(外键) 和 Id 字段是主键(大整数) 这些表包含 100000(invoice) 和 450000(invoiceItem) 行


现在我必须编写一个查询,它将返回发票分类帐,其中发票 = 55 或 66,并且在某个日期范围内。 我还必须返回最后一个使用日期,其中包含该特定客户之前使用产品的日期。


输出应该是 OrderDate、InvoiceId、CustomerId、ProductId、LastTaken、PackageQty、PackagePrice


所以我写了以下查询

SELECT a.*, (
    SELECT MAX(ivv.orderdate)
    FROM invoice AS ivv , invoiceItem AS iiv 
    WHERE ivv.id=iiv.invoiceid
    AND iiv.ProductId=a.ProductId AND ivv.CustomerId=a.CustomerId AND ivv.orderDate<a.orderdate
) AS lastTaken FROM (
    SELECT iv.Id, iv.OrderDate, iv.CustomerId, iv.InvoiceFor, ii.ProductId,     
    ii.PackageQty, ii.PackagePrice
    FROM invoice AS iv, invoiceitem AS ii
    WHERE iv.id=ii.InvoiceId 
    AND iv.InvoiceFor IN (55,66)
    AND iv.Status=0 AND ii.Status=0 
    AND OrderDate BETWEEN '2011-01-01' AND '2011-12-31'
    ORDER BY iv.orderdate, iv.Id ASC 
) AS a

但我总是超时。我将如何解决这个问题???

这个查询的解释如下:

【问题讨论】:

  • 这些表存在哪些索引?
  • Id 是两个表的主键
  • InvoiceItem.InvoiceId 是否已编入索引?这在几乎任何情况下都会有所帮助。
  • 是invoiceitem表的invoiceid是包含invoice表id值的foregin key
  • 我相信MySQL默认为外键创建索引。

标签: mysql optimization query-optimization


【解决方案1】:

在 OrderDate 和 InvoiceFor 属性上创建索引。它应该更快。

【讨论】:

  • @G.M.NazmulHossain 在选择前输入 EXPLAIN (EXPLAIN SELECT ...) 并在此处发布输出。
  • id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY ALL \N \N \N \N 66057 3 DERIVED iv ALL PRIMARY,NewIndex1,NewIndex2 \N \N \N 73444 使用文件排序 3 DERIVED ii ref FK_invoiceitem FK_invoiceitem 9 test1.iv.Id 1 使用 where 2 DEPENDENT SUBQUERY ivv ALL PRIMARY,NewIndex1 \N \N \N 73444 使用 where 2 DEPENDENT SUBQUERY iiv ref FK_invoiceitem FK_invoiceitem 9 test1.ivv.Id 1 使用 where
  • 最好检查图像facebook.com/…
【解决方案2】:

关于查询本身的两点:

  1. 学习使用正确的 JOIN 语法。在WHERE 子句中进行连接就像用莎士比亚英语写问题一样。
  2. 子查询中的ORDER BY 应该在最高级别之外。

但是,这些都不会影响性能。问题是SELECT 子句中的子查询。我认为问题在于SELECT 子句中的子查询没有直接加入这两个表。尝试将iiv.InvoiceId = ivv.InvoiceId 包含在最好的和ON 子句中。

如果这不起作用,请尝试索引策略。以下索引应该可以提高该子查询的性能:

  • InvoiceItem(ProductId) 上的索引
  • 发票索引(CustomerId、OrderDate)

这应该允许 MySQL 从索引运行子查询,而不是全表扫描,这应该是一个很大的性能改进。

【讨论】:

    猜你喜欢
    • 2012-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多