MySQL中的视图及性能问题 zz
上一篇 / 下一篇 2007-12-30 21:57:41 / 个人分类:LAMP
视图是MySQL 5.0中增加的三大新功能之一(另外两个是存储过程与触发器),也是一般稍微“高级”一点的数据库所必需要有的功能。MySQL在定义视图上没什么限制,基本上所有的查询都可定义为视图,并且也支持可更新视图(当然只有在视图和行列与基础表的行列之间存在一一对应关系时才能更新),因此从功能上说MySQL的视图功能已经很完善了。
:}8mfE!v ]V%^u?0
)C| |eM.r0然而若要在应用中使用视图,还需要了解处理视图时的性能,而MySQL在这方面问题是比较大的,需要特别注意。首先要知道MySQL在处理视图时有两种算法,分别称为MERGE和TEMPTABLE。在执行"CREATE VIEW"语句时可以指定使用哪种算法。所谓MERGE是指在处理涉及到视图的操作时,将对视图的操作根据视图的定义进行展开,有点类似于C语言中的宏展开。比如设有以下的表(类似于博客中的评论):木铎校园 BBS 社区PC)_\,?
CREATE TABLE `comment` (
`id` int(11) NOT NULL,
`user_id` int(11) default NULL,
`content` varchar(255) default NULL,
PRIMARY KEY (`id`),
KEY `idx_comment_uid` (`user_id`)
) ENGINE=InnoDB;
S#Xi [4n6o$g0假设user_id < 10000的用户为VIP用户,我们可以这样创建一个视图来表示VIP用户的评论:木铎校园 BBS 社区'r)h a3x-ar
CREATE VIEW vip_comment AS SELECT * FROM comment WHERE user_id < 10000;木铎校园 BBS 社区Z|9cqC
这时我们在操作vip_comment视图时使用的就是MERGE算法。如:木铎校园 BBS 社区(t)Y!HV!|2I
mysql > EXPLAIN EXTENDED SELECT count(*) FROM vip_comment WHERE user_id < 0;
+----+-------------+---------+-------+-----------------+-----------------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+-----------------+-----------------+---------+------+------+--------------------------+
| 1 | SIMPLE | comment | range | idx_comment_uid | idx_comment_uid | 5 | NULL | 10 | Using where; Using index |
+----+-------------+---------+-------+-----------------+-----------------+---------+------+------+--------------------------+
mysql> show warnings;
+-------+------+---------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message |
+-------+------+---------------------------------------------------------------------------------------------------------------------------------------+
| Note | 1003 | select count(0) AS `count(*)` from `test`.`comment` where ((`test`.`comment`.`user_id` < 0) and (`test`.`comment`.`user_id` < 10000)) |
+-------+------+---------------------------------------------------------------------------------------------------------------------------------------+
EU7wM KF0可以看到,对vip_comment的操作已经被扩展为对comment表的操作。木铎校园 BBS 社区J(N)Z*{2m9_+\
gLkp\G"Jf1sL2C0p0一般来说在能够使用MERGE算法的时候MySQL处理视图上没什么性能问题,但并非在任何时候都能使用MERGE算法。事实上,只要视图的定义稍稍有点复杂,MySQL就没办法使用MERGE算法了。准确的说,只要视图定义中使用了以下SQL构造块就无法使用MERGE算法:木铎校园 BBS 社区G8eH^G0L)?OQY!R
/X#|8N\\'r9|4i0
:u;vDR/dMsc&C0比如我们希望使用如下的视图来表示每个用户的评论数,即:
:}8mfE!v ]V%^u?0
)C| |eM.r0然而若要在应用中使用视图,还需要了解处理视图时的性能,而MySQL在这方面问题是比较大的,需要特别注意。首先要知道MySQL在处理视图时有两种算法,分别称为MERGE和TEMPTABLE。在执行"CREATE VIEW"语句时可以指定使用哪种算法。所谓MERGE是指在处理涉及到视图的操作时,将对视图的操作根据视图的定义进行展开,有点类似于C语言中的宏展开。比如设有以下的表(类似于博客中的评论):木铎校园 BBS 社区PC)_\,?
CREATE TABLE `comment` (
`id` int(11) NOT NULL,
`user_id` int(11) default NULL,
`content` varchar(255) default NULL,
PRIMARY KEY (`id`),
KEY `idx_comment_uid` (`user_id`)
) ENGINE=InnoDB;
S#Xi [4n6o$g0假设user_id < 10000的用户为VIP用户,我们可以这样创建一个视图来表示VIP用户的评论:木铎校园 BBS 社区'r)h a3x-ar
CREATE VIEW vip_comment AS SELECT * FROM comment WHERE user_id < 10000;木铎校园 BBS 社区Z|9cqC
这时我们在操作vip_comment视图时使用的就是MERGE算法。如:木铎校园 BBS 社区(t)Y!HV!|2I
mysql > EXPLAIN EXTENDED SELECT count(*) FROM vip_comment WHERE user_id < 0;
+----+-------------+---------+-------+-----------------+-----------------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+-----------------+-----------------+---------+------+------+--------------------------+
| 1 | SIMPLE | comment | range | idx_comment_uid | idx_comment_uid | 5 | NULL | 10 | Using where; Using index |
+----+-------------+---------+-------+-----------------+-----------------+---------+------+------+--------------------------+
mysql> show warnings;
+-------+------+---------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message |
+-------+------+---------------------------------------------------------------------------------------------------------------------------------------+
| Note | 1003 | select count(0) AS `count(*)` from `test`.`comment` where ((`test`.`comment`.`user_id` < 0) and (`test`.`comment`.`user_id` < 10000)) |
+-------+------+---------------------------------------------------------------------------------------------------------------------------------------+
EU7wM KF0可以看到,对vip_comment的操作已经被扩展为对comment表的操作。木铎校园 BBS 社区J(N)Z*{2m9_+\
gLkp\G"Jf1sL2C0p0一般来说在能够使用MERGE算法的时候MySQL处理视图上没什么性能问题,但并非在任何时候都能使用MERGE算法。事实上,只要视图的定义稍稍有点复杂,MySQL就没办法使用MERGE算法了。准确的说,只要视图定义中使用了以下SQL构造块就无法使用MERGE算法:木铎校园 BBS 社区G8eH^G0L)?OQY!R
- 聚集函数
- DISTINCT
- GROUP BY
- HAVING
- 集合操作(在MySQL中只有UNION, UNION ALL,没有EXCEPT和INTERSECT)
- 子查询
/X#|8N\\'r9|4i0
:u;vDR/dMsc&C0比如我们希望使用如下的视图来表示每个用户的评论数,即:
