簡體   English   中英

mysql查詢優化(索引錯誤?)避免文件排序

[英]mysql query optimization (wrong indexes?) avoid filesort

我會盡力向自己解釋。 我有一個名為“ artikli”的數據庫,其中包含大約100萬條記錄。 在此表上,我運行許多不同的查詢,但是當存在ORDER by時,有1種查詢會引起問題(較長的執行時間)。

這是我的表結構:

CREATE TABLE IF NOT EXISTS artikli (
  id int(11) NOT NULL,
  name varchar(250) NOT NULL,
  datum datetime NOT NULL,
  kategorije_id int(11) default NULL,
  id_valute int(11) default NULL,
  podogovoru int(1) default '0',
  cijena decimal(10,2) default NULL,
  valuta int(1) NOT NULL default '0',
  cijena_rezerva decimal(10,0) NOT NULL,
  cijena_kupi decimal(10,0) default NULL,
  cijena_akcija decimal(10,2) NOT NULL,
  period int(3) NOT NULL default '30',
  dostupnost enum('svugdje','samobih','samomojgrad','samomojkanton') default 'svugdje',
  zemlja varchar(10) NOT NULL,
  slike varchar(500) NOT NULL,
  od_s varchar(34) default NULL,
  od_id int(10) unsigned default NULL,
  vrsta int(1) default '0',
  trajanje datetime default NULL,
  izbrisan int(1) default '0',
  zakljucan int(1) default '0',
  prijava int(3) default '0',
  izdvojen decimal(1,0) NOT NULL default '0',
  izdvojen_kad datetime NOT NULL,
  izdvojen_datum datetime NOT NULL,
  sajt int(1) default '0',
  PRIMARY KEY  (id),
  KEY brend (brend),
  KEY kanton (kanton),
  KEY datum (datum),
  KEY cijena (cijena),
  KEY kategorije_id (kategorije_id,podogovoru,sajt,izdvojen,izdvojen_kad,datum)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

這是查詢:

SELECT artikli.datum as brojx, 
     artikli.izdvojen as i, 
     artikli.izdvojen_kad as ii, 
     artikli.cijena as cijena, artikli.name 
FROM artikli 
WHERE artikli.izbrisan=0 and artikli.prodano!=3 
     and artikli.zavrseno=0 and artikli.od_id!=0 
     and (artikli.sajt=0 or (artikli.sajt=1 and artikli.dostupnost='svugdje')) 
     and kategorije_id IN (18) 
ORDER by i DESC, ii DESC, brojx DESC 
LIMIT 0,20

我想做的是避免Filesort,這很慢。

如果您提供了查詢的解釋計划,那將是一個很大的幫助。

您為什么認為它是導致問題的文件排序? 查看查詢,您似乎在應用大量過濾-這大大減少輸出集-但沒有一個可以使用可用索引。

artikli.izbrisan=0 and artikli.prodano!=3 
 and artikli.zavrseno=0 and artikli.od_id!=0 
 and (artikli.sajt=0 or (artikli.sajt=1 and artikli.dostupnost='svugdje')) 
 and kategorije_id IN (18) 

盡管我不知道您的數據的模式是什么,但我懷疑通過在上添加索引,您可能會獲得更多好處:

kategorije_id,izbrisan,sajt

所有其他索引是否真的已經被使用?

盡管你會通過非規范化所有這些布爾得到您的降壓很多更多的收益(假設表是標准化入手,有沒有隱藏的功能依賴於那里)。

C。

問題是您在ORDER BY使用的izdvojenizdvojen_kaddatum列上沒有索引。

請注意,您以kategorije_id開頭的大索引不能用於排序(盡管它對where子句有所幫助),因為排序所依據的列位於索引的末尾。

實際上,排序依據不是您想要的索引的基礎...而是您要與查詢基本匹配的CRITERIA ...過濾掉較小的數據集,您將獲得較小的表集...我會稍微更改WHERE子句,但是您將最了解您的數據。 首先將最小的期望條件放在首位,並確保以此為基礎的索引...類似

WHERE  
       artikli.izbrisan = 0 
   and artikli.zavrseno = 0 
   and artikli.kategorije_id IN (18)  
   and artikli.prodano != 3
   and artikli.od_id != 0
   and (    artikli.sajt = 0 
        or (     artikli.sajt = 1
             and artikli.dostupnost='svugdje')
           )

並具有(izbrisan,zavrseno,kategorije_id)的復合索引...我已將其他!=比較設置為模式,因為它們不是特定的鍵值,相反,它們都是除所討論的值之外的所有值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM