3

我有如下定义的视图:

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 条记录的速度增长。

当我在视图上运行选择时,大约需要 25 秒。我担心随着表的大小继续增长,此查询的性能将迅速下降。

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

解释

在上面的 select 上运行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;
4

2 回答 2

4

添加索引(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你也可以尝试改变to并比较性能。在这种情况下,视图也可以定义为:a(b_id)references b(id)JOINLEFT 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 ;
于 2013-09-09T22:49:19.003 回答
2

您正在使用 InnoDB - 很高兴您提到了这一点。

这是一个清单:

  • 优化您的餐桌

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

OPTIMIZE TABLE b;
OPTIMIZE TABLE a;

在以下位置查看有关 InnoDB 优化的更多信息:MySQL

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

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

  • a.b_id - 可能是外

  • 最后 - 检查你的内存,考虑使用 InnoDB 的缓冲区选项。

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

于 2013-09-09T22:37:23.973 回答