0

私は2つのテーブルを持っています。これらのテーブルの作成コマンドは次のとおりです

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 サーバー (ローカル) でこのクエリを実行していますが、ほとんどの場合、タイムアウトが発生しました。このクエリを最適化するにはどうすればよいですか?

このクエリの Explain は次のとおりです。 ここに画像の説明を入力

今、私は適用します

create index invoiceid_productid 
  on invoiceItem(invoiceId, productId)

その後、説明結果は ここに画像の説明を入力

4

2 に答える 2

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 に答える
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 に答える