0

我有两张桌子。这些表的创建命令如下

CREATE TABLE `invoice` (
  `Id` bigint(20) NOT NULL,
  `VersionNumber` int(11) NOT NULL,
  `CreationDate` datetime default NULL,
  `ModificationDate` datetime default NULL,
  `CreateBy` bigint(20) default NULL,
  `ModifyBy` bigint(20) default NULL,
  `BusinessId` varchar(255) character set utf8 default NULL,
  `Status` int(11) default NULL,
  `VendorId` bigint(20) default NULL,
  `CustomerId` bigint(20) default NULL,
  `OrderDate` date default NULL,
  `ExpectedDate` date default NULL,
  `DeliveryDate` date default NULL,
  `InvoiceFor` int(11) default NULL,
  `Reference` varchar(255) character set utf8 default NULL,
  `Agent` varchar(255) character set utf8 default NULL,
  `BnAgent` varchar(255) character set utf8 default NULL,
  `Note` varchar(255) character set utf8 default NULL,
  `HasVoucher` char(1) character set utf8 default NULL,
  PRIMARY KEY  (`Id`),
  KEY `CustomerId` (`CustomerId`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `invoiceitem` (
  `Id` bigint(20) NOT NULL,
  `VersionNumber` int(11) NOT NULL,
  `CreationDate` datetime default NULL,
  `ModificationDate` datetime default NULL,
  `CreateBy` bigint(20) default NULL,
  `ModifyBy` bigint(20) default NULL,
  `BusinessId` varchar(255) default NULL,
  `Status` int(11) default NULL,
  `InvoiceId` bigint(20) default NULL,
  `ProductId` bigint(20) default NULL,
  `PackageQty` decimal(19,5) default NULL,
  `PackagePrice` decimal(19,5) default NULL,
  `ItemPerPackage` decimal(19,5) default NULL,
  `ItemQty` decimal(19,5) default NULL,
  `ItemPrice` decimal(19,5) default NULL,
  `StoreQty` decimal(19,5) default NULL,
  `RevenuePercent` decimal(19,5) default NULL,
  `PurchasePrice` decimal(19,5) default NULL,
  `Vat` decimal(19,5) default NULL,
  `TotalAmount` decimal(19,5) default NULL,
  `InvoiceItemFor` int(11) default NULL,
  `LifeTimeUptoDate` datetime default NULL,
  PRIMARY KEY  (`Id`),
  KEY `invoiceid_productid` (`InvoiceId`,`ProductId`),
  KEY `ProductId` (`ProductId`),
  CONSTRAINT `FK_invoiceitem` FOREIGN KEY (`InvoiceId`) REFERENCES `invoice` (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

此查询的目的是 向管理员显示发票列表。他需要查看发票日期、发票编号、客户 ID、产品 ID,以及客户是否在之前购买过该产品,然后再查看之前的日期。

现在查询

SELECT iv.id, iv.CustomerId, ii.ProductId, MAX(iv2.orderdate) AS PriviousDate
FROM invoice AS iv
INNER JOIN invoice AS iv2 
    ON iv.CustomerId=iv2.CustomerId 
    AND iv.OrderDate>iv2.OrderDate
INNER JOIN invoiceItem AS ii 
    ON iv.id=ii.invoiceId 
INNER JOIN invoiceItem AS ii2 
    ON  iv2.id=ii2.invoiceId 
    AND ii.ProductId=ii2.ProductId
WHERE iv.Status=0 
    AND ii.Status=0 
    AND iv2.Status=0 
    AND ii2.Status=0
GROUP BY ii.ProductId, iv.CustomerId

这里 iv.id 和 ii.id 是主键 customerId 和 Productid 字段也是索引和 invoiceId 是foreginkey (iv.id=ii.invoiceId )

我在我的 MySql 服务器(本地)中运行这个查询,但大多数时候我都超时了。如何优化此查询?

该查询的解释如下: 在此处输入图像描述

现在我申请

create index invoiceid_productid 
  on invoiceItem(invoiceId, productId)

之后解释结果是 在此处输入图像描述

4

2 回答 2

0

这里不多(看看你的索引是什么会很有帮助)但假设发票ID随着发票日期的增加而增加......我怀疑这可能会稍微快一点:

SELECT iv.id, iv.CustomerId, ii.ProductId, MAX(iv2.orderdate) AS PriviousDate
FROM invoice AS iv
INNER JOIN invoice AS iv2 
   ON iv.CustomerId=iv2.CustomerId 
   AND iv.id>iv2.id
INNER JOIN invoiceItem AS ii 
   ON iv.id=ii.invoiceId 
INNER JOIN invoiceItem AS ii2 
   ON  iv2.id=ii2.invoiceId 
   AND ii.ProductId=ii2.ProductId
   AND ii.invoiceId>ii2.invoiceId
WHERE iv.Status=0 
   AND ii.Status=0 
   AND iv2.Status=0 
   AND ii2.Status=0
GROUP BY ii.ProductId, iv.CustomerId

但是您确实需要在 invoiceItem 表中的 ProductId、Status 和 InvoiceId 上建立一个索引,然后它才能明显更快。

于 2012-10-08T11:11:23.787 回答
0

查看您的EXPLAIN结果,问题显然出在invoiceItem表格上。它有 200,000 行,MySQL 没有使用任何索引来访问它。

因此,您应该考虑创建索引以加快对其的访问速度。

我模拟了你的桌子:

create table invoice (
  id int auto_increment not null,
  customerid int not null,
  orderdate timestamp not null,
  status int default 0 not null,
  primary key(id)
);
create table invoiceItem (
  id int auto_increment not null,
  invoiceId int not null,
  productId int not null,
  status int default 0 not null,
  primary key (id)
);

我创建了这些索引:

create index invoiceId on invoiceItem(invoiceId);
create index cod on invoice(customerid, orderdate);
create index stat on invoice(status);

我的 EXPLAIN (在空表上)现在所有表都使用 type ref

您还可以查看适用于 MySQL 的本教程;-)

于 2012-10-08T11:10:12.103 回答