我的视图定义如下:
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;
答案 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;
了解有关InnoDB优化的更多信息
我不明白为什么你为你的每一列创建了一个密钥,这有点多余 - 因为你可以将多个列作为单个密钥(复合索引)绑定 - 特别是如果您只是将单个列与另一个表中的另一列进行比较。理想情况下,您也可以按照与组相同的顺序创建索引。
从逻辑上讲,他们只会在使用GROUP BY时比较单个键索引,而不是对每个键进行排序,然后将它们放在正确的值旁边。
a.b_id - 可以是FOREIGN KEY
最后 - 检查你的记忆,考虑使用InnoDB的缓冲选项。
希望有所帮助。为了帮助他人,如果其中一个人帮助了你,请留下评论,哪个影响最大。