如何优化MySQL视图的性能

时间:2013-09-09 20:08:39

标签: mysql performance innodb

我的视图定义如下:

CREATE VIEW vw_data_summary AS
SELECT
    a.b_id AS b_id
    b.txt_field AS b_txt_field
    a.txt_field AS a_txt_field
    SUM(a.amount) AS amount
FROM
    a JOIN b
WHERE
    a.b_id = b.id
GROUP BY
    a.b_id, b.txt_field, a.txt_field

a有650,000条记录,而表b有3,200条记录。 a.b_id上有一个索引。表格在表a上以每天1,500条记录的速度增长,在表格b上每天增加50条记录。

当我在视图上运行select时,大约需要25秒。我担心随着表格的大小不断增加,这个查询的性能会迅速下降。

我可以对单个表或视图本身做些什么来改善性能?

EXPLAIN

在上面的选择上运行explain会产生以下输出:

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE          b   ALL PRIMARY NULL    NULL    NULL    3078    Using temporary; Using filesort
1   SIMPLE          a   ref b_id    b_id    4   b.id    134  

表定义

CREATE TABLE IF NOT EXISTS `b` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `txt_field` varchar(50) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `txt_field` (`txt_field`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1;

CREATE TABLE IF NOT EXISTS `a` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `b_id` int(11) NOT NULL,
  `txt_field` varchar(255) NOT NULL,
  `amount` decimal(10,2) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `txt_field` (`txt_field`),
  KEY `b_id` (`b_id`),
  KEY `new_index` (`txt_field`,`b_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1;

2 个答案:

答案 0 :(得分:3)

(b_id, txt_field, amount)上添加索引并使用以下内容创建视图:

CREATE VIEW vw_data_summary_2 AS
SELECT
    a.b_id AS b_id
    b.txt_field AS b_txt_field
    a.txt_field AS a_txt_field
    SUM(a.amount) AS amount
FROM
    a JOIN b
      ON
    a.b_id = b.id
GROUP BY
    a.b_id, a.txt_field ;

如果foreign key a(b_id) references b(id) JOIN,您还可以尝试将LEFT JOIN更改为CREATE VIEW vw_data_summary_4 AS SELECT a.b_id AS b_id (SELECT b.txt_field FROM b WHERE a.b_id = b.id) AS b_txt_field a.txt_field AS a_txt_field SUM(a.amount) AS amount FROM a GROUP BY a.b_id, a.txt_field ; 并比较效果。在这种情况下,视图也可以定义为:

{{1}}

答案 1 :(得分:2)

你正在使用InnoDB - 很高兴你提到过。

这是一份清单:

  • 优化您的表格

这将重新组织您服务器上的表以便更快地输入/输出

OPTIMIZE TABLE b;
OPTIMIZE TABLE a;

MySQL

了解有关InnoDB优化的更多信息

我不明白为什么你为你的每一列创建了一个密钥,这有点多余 - 因为你可以将多个列作为单个密钥(复合索引)绑定 - 特别是如果您只是将单个列与另一个表中的另一列进行比较。理想情况下,您也可以按照与组相同的顺序创建索引。

从逻辑上讲,他们只会在使用GROUP BY时比较单个键索引,而不是对每个键进行排序,然后将它们放在正确的值旁边。

  • a.b_id - 可以是FOREIGN KEY

  • 最后 - 检查你的记忆,考虑使用InnoDB的缓冲选项。

希望有所帮助。为了帮助他人,如果其中一个人帮助了你,请留下评论,哪个影响最大。