2012-05-10 50 views
1

我想连接两个MySQL表并将其存储为视图,因此我可以在应用程序中解决此视图而不是查询两个表。但这种看法发生得非常缓慢。MySQL视图的优化

这是我的表:

CREATE TABLE spectrumsets (
    setid INT(11) NOT NULL, 
    timestampdt INT(11) NULL DEFAULT NULL, 
    timestampd INT(10) UNSIGNED NOT NULL, 
    timestampt INT(10) UNSIGNED NOT NULL, 
    device INT(11) NOT NULL, 
    methodname VARCHAR(50) NOT NULL, 
    PRIMARY KEY (setid), 
    UNIQUE INDEX setid_idx (setid), 
    UNIQUE INDEX timestamp_device_idx (timestampd, timestampt, device), 
    INDEX device_fk (device), 
    INDEX timestampd_idx (timestampd), 
    CONSTRAINT device_fk FOREIGN KEY (device) 
     REFERENCES spectrumdevices (deviceid) 
) 
COLLATE='utf8_general_ci' 
ENGINE=InnoDB 

CREATE TABLE spectrumdata (
    valueid INT(11) NOT NULL AUTO_INCREMENT, 
    spectrumset INT(11) NOT NULL, 
    wavelength DOUBLE NULL DEFAULT NULL, 
    intensity DOUBLE NULL DEFAULT NULL, 
    PRIMARY KEY (valueid), 
    INDEX spectrumset_idx (spectrumset), 
    CONSTRAINT spectrumset_fk FOREIGN KEY (spectrumset) 
     REFERENCES spectrumsets (setid) 
) 
COLLATE='utf8_general_ci' 
ENGINE=InnoDB 

这是我的看法:

SELECT spectrumsets.timestampd,spectrumsets.timestampt,spectrumsets.device, 
    spectrumdata.wavelength,spectrumdata.intensity 
FROM spectrumdata INNER JOIN spectrumsets ON spectrumdata.spectrumset= 
    spectrumsets.setid 
WHERE spectrumdata.wavelength>0 
ORDER BY spectrumsets.timestampd,spectrumsets.timestampt,spectrumsets.device, 
    spectrumdata.wavelength 

我的机器上的select count(*)需要385.516秒和成果转化为82923705分的记录,所以一个相当大的数据集

我已经找到了这个link,但仍然不完全明白是什么错误。

UPDATE:

EXPLAIN给出了这样的结果:

"id","select_type","table","type","possible_keys","key","key_len","ref","rows","Extra" 
"1","SIMPLE","spectrumsets","index","PRIMARY,setid_idx","timestamp_device_idx","12",NULL,"327177","Using index; Using temporary; Using filesort" 
"1","SIMPLE","spectrumdata","ref","spectrumset_idx","spectrumset_idx","4","primprod.spectrumsets.setid","130","Using where" 
+2

你使用EXPLAIN? –

+0

是否运行'分析表谱数据频谱集?有什么区别? – Bohemian

+1

什么是你的buffer_pool_size?看起来数据集不适合内存,所以InnoDB可能在进行全表扫描时强奸磁盘。 –

回答

2

解释表明,查询被击中的加入指数(好的),但是如果使用了临时表和文件排序查询的其余部分。

这是出于两个原因:

  • 的where子句不打指数
  • order by子句没有击中指数

在评论,你说删除where子句导致了很大的改进;这表明您需要光谱集,波长上的复合索引,假设波长具有相当数量的可能值(如果只有10个值,则索引可能不会做任何事情)。

如果您将“order by”子句排除在视图之外,应该快得多 - 并且有一个很好的例子,可以让查询提取数据而不是视图来确定排序顺序。我猜测大多数查询都会对数据非常有选择性 - 限制几个时间戳;通过在视图中嵌入订单,您每次都要付出排序的代价。

如果您确实必须在视图中具有“排序依据”,请创建一个索引,该索引包含“排序依据”顺序中的所有字段,并在前面加入连接。例如:

UNIQUE INDEX timestamp_device_idx(SET_ID,timestampd,timestampt,设备),

+0

+1。这是正确的答案,但MySQL 5。0+可以使用[索引合并](http://dev.mysql.com/doc/refman/5.0/en/index-merge-optimization.html)使用多个索引。我会删除相反的声明或澄清。此外,对于该复合索引,请在索引中放置使用范围的列(本例中为波长列,请参阅WHERE波长> 0),因为对索引使用范围会使剩余部分无效。除此之外,首先放置最高基数的列。 –

+0

做了一些测试:删除ORDER BY子句将大约385秒的性能时间减少到大约285秒,但也将WHERE子句删除到大约48秒!所以我认为我真的需要将ORDER BY子句移到调用应用程序,而且还要移动WHERE子句。对我而言,这不是一个真正的问题,但我仍然不完全明白发生了什么:-(对innodb_buffer_pool_size会有一些帮助,但对视图的SQL语句的构造也是如此 – waanders

+0

这真是一个很好的迹象表明它是在哪里从而导致问题;我将相应地编辑答案。 –