易失性数据查询的优化

时间:2010-02-24 15:16:48

标签: mysql optimization

我正在尝试解决a到mysql-5.0 db的延迟问题。

  • 查询本身非常简单:SELECT SUM(items) FROM tbl WHERE col = 'val'
  • col上有一个索引,在最坏的情况下总和不超过10000个值(count(items)的所有值的平均值col大约为10)。< / LI>
  • 该表最多有2M行。
  • 查询运行得足够频繁,有时执行时间会达到10秒,尽管其中99%采用&lt;&lt; 1秒
  • 查询实际上并不可缓存 - 在几乎所有情况下,每个查询都会在下一分钟插入到该表中,并且显示旧值是不可能的(结算信息)。
  • 键足够好 - 约100%点击

我正在寻找的结果是每一个查询&lt; 1秒。有没有办法在不更改表格的情况下改善选择时间?或者,是否有任何有趣的变化有助于解决问题?我想过只需要一张表,在每次插入后立即更新每个col的当前总和 - 但也许有更好的方法可以做到这一点?

2 个答案:

答案 0 :(得分:2)

另一种方法是添加摘要表:

create table summary ( col varchar(10) primary key, items int not null );

并向tbl添加一些触发器,以便:

插入时

insert into summary values( new.col, new.items ) 
on duplicate key update set summary.items = summary.items + new.items;

关于删除:

update summary set summary.items = summary.items - old.items where summary.col = old.col

更新:

update summary set summary.items = summary.items - old.items where summary.col = old.col;
update summary set summary.items = summary.items + new.items where summary.col = new.col;

这会降低您的插入速度,但允许您在

的摘要表中单击一行
select items from summary where col = 'val';

这个问题的最大问题是引导汇总表的值。如果您可以使应用程序脱机,则可以使用tbl中的值轻松初始化摘要。

insert into summary select col, sum(items) from tbl group by col;

但是,如果您需要保持服务运行,则要困难得多。如果您有副本,则可以停止复制,构建摘要表,安装触发器,重新启动复制,然后将服务故障转移到使用副本,然后在已停用的主服务器上重复此过程。

如果你不能这样做,那么你可以一次更新摘要表一个col的值,以减少影响:

lock table write tbl, summary; 
delete from summary where col = 'val';
insert into summary select col, sum(items) from tbl where col = 'val';
unlock tables;

或者如果你能忍受长时间的停电:

lock table write tbl, summary;
delete from summary;
insert into summary select col, sum(items) from tbl group by col;
unlock tables;

答案 1 :(得分:1)

覆盖索引应该有所帮助:

create index cix on tbl (col, items);

这样可以在不读取数据文件的情况下执行求和 - 这应该更快。

您还应该跟踪密钥缓冲区的有效性,以及是否需要为其分配更多内存。这可以通过轮询服务器状态并观察'key%'值来完成:

SHOW STATUS LIKE 'Key%';

MySQL Manual - show status

key_read_requests(即索引查找的数量)与key_reads之间的比率(即需要从磁盘读取索引块的请求数量)非常重要。磁盘读取次数越多,查询运行得越慢。您可以通过增加配置文件中的密钥缓冲区大小来改进这一点。

相关问题