我目前正在尝试提高MySQL表的SELECTS的速度,并且希望就改进它的方法提出任何建议。
该表中有3亿条记录,并且该表具有结构标签,日期和值。主键是标签和日期的组合键。该表包含约600个唯一标签的信息,其中大多数平均包含约40万行,但范围可能从2000行到超过1100万行。
针对表运行的查询为:
SELECT date, value FROM table WHERE tag = "a" AND date BETWEEN 'x' and 'y' ORDER BY date
....并且几乎没有(如果有的话)插入。
我曾尝试通过标签将数据划分为多个分区,但是速度似乎没有增加。
花点时间在这里阅读我的答案:(与您的书卷相似)
在0.02秒内扫描5亿行,1500万行。
MySQL和NoSQL:帮助我选择合适的一个
然后将表引擎修改为innodb,如下所示:
create table tag_date_value ( tag_id smallint unsigned not null, -- i prefer ints to chars tag_date datetime not null, -- can we make this date vs datetime ? value int unsigned not null default 0, -- or whatever datatype you require primary key (tag_id, tag_date) -- clustered composite PK ) engine=innodb;
您可以考虑将以下内容作为主键:
primary key (tag_id, tag_date, value) -- added value save some I/O
但是仅当值不是某些大型varchar类型时!
像以前一样查询:
select tag_date, value from tag_date_value where tag_id = 1 and tag_date between 'x' and 'y' order by tag_date;
希望这可以帮助 :)
编辑
哦,忘记了-不要使用altertable将引擎类型从mysiam更改为innodb,而是将数据转储到csv文件中,然后重新导入到新创建的空innodb表中。
请注意,我在导出过程中正在对数据进行排序-聚集索引是关键!
出口
select * into outfile 'tag_dat_value_001.dat' fields terminated by '|' optionally enclosed by '"' lines terminated by '\r\n' from tag_date_value where tag_id between 1 and 50 order by tag_id, tag_date; select * into outfile 'tag_dat_value_002.dat' fields terminated by '|' optionally enclosed by '"' lines terminated by '\r\n' from tag_date_value where tag_id between 51 and 100 order by tag_id, tag_date; -- etc...
进口
以正确的顺序导入到表中!
start transaction; load data infile 'tag_dat_value_001.dat' into table tag_date_value fields terminated by '|' optionally enclosed by '"' lines terminated by '\r\n' ( tag_id, tag_date, value ); commit; -- etc...