一个合理的数据存取实现和一个拙劣的实现相比,在性能方面的差异经常会超出一个甚至几个数量级。SQL 语句执行所消耗的最大两部分资源就是IO和CPU。
案例一、
在我们的示例网站系统中,现在要实现每个用户查看各自相册列表(假设每个列表显示10 张相片)的时候,能够在相片名称后面显示该相片的留言数量。
1、通过“SELECT id,subject,url FROM photo WHERE user_id = ? limit 10” 得到第一页的相片相关信息;
2、通过第1 步结果集中的10个相片id 循环运行十次“SELECT COUNT(*) FROM photo_comment WHERE photh_id = ?” 来得到每张相册的回复数量然后再瓶装展现对象。
或者
1、和上面完全一样的操作步骤;
2、通过程序拼装上面得到的10 个photo 的id,再通过in 查询“SELECT photo_id,count(*) FROM photo_comment WHERE photo_id in (?) GROUP BY photo_id” 一次得到10 个photo 的所有回复数量,再组装两个结果集得到展现对象。
从MySQL 执行的SQL 数量来看,第一种解决方案为11条SQL 语句,第二种解决方案为2 条SQL 语句(1+1);
从应用程序与数据库交互来看,第一种为11 次,第二种为2 次;
从数据库的IO 操作来看,简单假设每次SQL 为1 个IO,第一种最少11 次IO,第二种小于等于11次IO,而且只有当数据非常之离散的情况下才会需要11 次;
==========================可爱的分隔符=======================
案例二、
在群组简介页面需要显示群名称和简介,每个群成员的nick_name,以及群主的个人签名信息。
需求中所需信息存放在以下四个表中:user,user_profile,groups,user_group
一条SQL 语句搞定所有事情:
SELECT name,description,user_type,nick_name,sign
FROM groups,user_group,user ,user_profile
WHERE groups.id = ?
AND groups.id = user_group.group_id
AND user_group.user_id = user.id
AND user_profile.user_id = user.id -----对非群主的profile信息进行的访问,造成了资源的浪费
或者分两步搞定:
首先取得所有需要展示的group 的相关信息和所有群组员的nick_name 信息和组员类别:
SELECT name,description,user_type,nick_name
FROM groups,user_group,user
WHERE groups.id = ?
AND groups.id = user_group.group_id
AND user_group.user_id = user.id
然后在程序中通过上面结果集中的user_type 找到群主的user_id 再到user_profile 表中取得群主的签名信息:
SELECT sign FROM user_profile WHERE user_id = ?