数据库设计调优(二)
五 分表技术
分表技术有水平分割和垂直分割
水平分割:当一张越来越大时候,即使添加索引还慢的话,我们可以使用水平分表,以qq用户表简单举例来具体的说明一下水平分表的操作思路.如我们在一个互联网上注册一个帐号,帐号很多,可能帐号表不止一个(如table1,table2,table3)。可以在我们进行注册的时候生成一个标识,然后对这个标识通过程序逻辑进行处理(如生成的是一个随机整数,对该整数进行除3求余的方式,如余1放到table1,余2放到table2,余0放到table3),放到相应的表中。访问该信息的时候,也通过注册的随机标识处理知道在哪个表,在相应的表中进行检索即可。
如下一个php代码:
首先我创建三张表 user0 / user1 /user2 , 然后我再创建 uuid表,该表的作用就是提供自增的id,
create table user0(
id int unsigned primary key ,
name varchar(32) not null default '',
pwd varchar(32) not null default '')
engine=myisam charset utf8;
create table user1(
id int unsigned primary key ,
name varchar(32) not null default '',
pwd varchar(32) not null default '')
engine=myisam charset utf8;
create table user2(
id int unsigned primary key ,
name varchar(32) not null default '',
pwd varchar(32) not null default '')
engine=myisam charset utf8;
create table uuid(
id int unsigned primary key auto_increment)engine=myisam charset utf8;
编写addUser.php
<?php
//注册一个用户
$con=mysql_connect("localhost","root","root");
if(!$con){
die("连接失败!");
}
mysql_select_db("temp",$con);
$name=$_GET['name'];
$pwd=$_GET['pwd'];
//这时我们先获取用户id,id是从uuid表获取
$sql="insert into uuid values(null)";
if(mysql_query($sql,$con)){
$id=mysql_insert_id();
}
//计算表名,就是,你应该把这个用户放入到哪个表
$talname='user'.$id%3;
$sql="insert into {$talname} values ($id,'$name','$pwd')";
if(mysql_query($sql,$con)){
echo '添加用户到 '.$talname.'ok';
}
mysql_close($con);
<?php
//注册一个用户
$con=mysql_connect("localhost","root","root");
if(!$con){
die("连接失败!");
}
mysql_select_db("temp",$con);
$id=intval($_GET['id']);
//计算表名
$tabname='user'.$id%3;
$sql="select pwd from {$tabname} where id=$id";
$res=mysql_query($sql,$con);
if($row=mysql_fetch_assoc($res)){
echo "在{$tabname}. 中发现 id号为 {$id}";
}
垂直分割:如果一张表某个字段,信息量大,但是我们很少查询,则可以考虑把这些字段,单独的放入到一张表中,这种方式称为垂直分割.这个举个简单的例子,NP的一张表有300个字段,在系统的实现中,经常select的字段都基本在100个固定的字段上,这样我们进行查询检索的时候会使用较多的IO,影响性能。建议把不经常使用的字段单独放到一张表中,有需要时,通过连表也可实现。这样即可大幅提高性能。
六 读写分离
随着一个网站的业务不断扩展,数据不断增加,数据库的压力也会越来越大,对数据库或者SQL的基本优化可能达不到最终的效果,我们可以采用读写分离的策略来改变现状。读写分离现在被大量应用于很多大型网站,这个技术也不足为奇了。
读写分离简单的说是把对数据库读和写的操作分开对应不同的数据库服务器,这样能有效地减轻数据库压力,也能减轻io压力。主数据库提供写操作,从数据库提供读操作,其实在很多系统中,主要是读的操作。当主数据库进行写操作时,数据要同步到从的数据库,这样才能有效保证数据库完整性。通过日志在从数据库重复主数据库的操作达到复制数据目的。这个复制比较好的就是通过异步方法,把数据同步到从数据库。主数据库同步到从数据库后,从数据库一般由多台数据库组成这样才能达到减轻压力的目的。读的操作怎么样分配到从数据库上?应该根据服务器的压力把读的操作分配到服务器,而不是简单的随机分配。mysql提供了MySQL-Proxy实现读写分离操作。
七 存储过程
在应用中可以的话尽量多,使用模块化编程,可以提高速度。
最后分享一个在网上找的20条数据库设计最佳实践
1.使用明确、统一的标明和列名,例如 School, SchoolCourse, CourceID。
2.数据表名使用单数而不是复数,例如 StudentCourse,而不是StudentCourses。
3.数据表名不要使用空格。
4.数据表名不要使用不必要的前缀或者后缀,例如使用School,而不是TblSchool,或者SchoolTable等等。
5.数据库中的密码要加密,到应用中再解密。(其实就是散列存储、单向加密)
6.使用整数作为ID字段,也许现在没有这个必要,但是将来需要,例如关联表,索引等等。
7.使用整数字段做索引,否则会带来很大的性能问题。
8.使用 bit 作为布尔字段,使用整数或者varcha是浪费。同时,这类字段应该以“Is”开头。
9.要经过认证才能访问数据库,不要给每一个用户管理员权限。
10.尽量避免使用“select *”,而使用“select [required_column_list]”以获得更好的性能。
11.假如程序代码比较复杂,使用ORM框架,例如hibernate,iBatis。ORM框架的性能问题可以通过详细的配置去解决。
12.分割不常使用的数据表到不同的物理存储以获得更好的性能。
13.对于关键数据库,使用安全备份系统,例如集群,同步等等。
14.使用外键,非空等限制来保证数据的完整性,不要把所有的东西都扔给程序。
15.缺乏数据库文档是致命的。你应该为你的数据库设计写文档,包括触发器、存储过程和其他脚本。
16.对于经常使用的查询和大型数据表,要使用索引。数据分析工具可以帮助你决定如何建立索引。
17.数据库服务器和网页服务器应该放在不同的机器上。这回提高安全性,并减轻CPU压力。
18.Image和blob字段不应该定义在常用的数据表中,否则会影响性能。
19.范式(Normalization)要按照要求使用以提高性能。Normalization做的不够会导致数据冗余,而过度Normalization 会导致太多的join和数据表,这两种情况都会影响性能。
20.多花点时间在数据库设计上,否则你将来会付出加倍的时间来偿还。