mysql查询优化(错误索引?)避免filesort

时间:2011-02-22 13:51:03

标签: mysql optimization indexing filesort

我会尽快解释自己。 我有一个名为'artikli'的数据库,它有大约1M的记录。 在这个表上,我运行了许多不同的查询,但是当存在ORDER时,一个特定的问题导致问题(执行时间长)。

这是我的表结构:

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。

3 个答案:

答案 0 :(得分:1)

如果您提供了查询的解释计划,那将是一个很大的帮助。

为什么你认为导致问题的文件输出?查看该查询,您似乎正在应用大量过滤 - 应该显着减少输出集 - 但是没有一个可以使用可用的索引。

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

是否所有其他索引都已被使用?

虽然通过对所有布尔值进行非规范化(假设表格已经规范化并且没有隐藏的函数依赖关系),你会得到更多的 LOT 更多的帮助。

下进行。

答案 1 :(得分:0)

问题是您没有izdvojen使用的izdvojen_kaddatumORDER BY列的索引。

请注意,以kategorije_id开头的大索引不能用于排序(尽管它会对where子句有所帮助),因为要排序的列位于索引的末尾。

答案 2 :(得分:0)

实际上,order by不是你想要的索引的基础...但是你想要的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)......我已经模仿了另一个!=比较之后,因为它们不是特定的键值,相反,它们都是除了有问题的值之外。