http://weibo.com/junsansi
                           君三思 2012-01




ORACLE & MYSQL

数据库模式设计漫谈
粒度 各有不同


SCHEMA/DB   TABLE      INDEX
  数据库         表         索引




                    每一种粒度都大有讲究
从数据库开始谈起



 核心:SHARDING、SHARDING、还是SHAREDING
随便放行不行?


              插呗~
              随便插呗~
              随便找地方插呗~
              …………….
              拆时怎么办?




想出? 哪有那么容易!
想进? 要进也进不来!
数据分片存储
• 垂直拆分

• 水平拆分
数据拆分(SHARDING)


                 垂直拆分(SCALE UP)
                   • 按业务
                   • 按类型




                 水平拆分(SCALE OUT)
                    • 按时间
                    • 按KEY HASH
天天打交道的表和列



       核心:适度、适量
关键因素!
         选择存储引擎:
         MyISAM vs InnoDB

         选择字符集:
         GBK vs UTF8


一经设定
  影响深远
表设计原则


• 控制字段数量(10列? 30列? 50列?)
• 控制记录数量(10w? 100w? 1000w?)
• 每个表都必须定义主键
• TEXT/BLOB等大字段单独存储
选择数据类型(1) – 整型
选择数据类型(2) – 字符型
选择数据类型(3) – 日期型
选择数据类型(4) – 综述


 必须正确理解的几个细节:
 • INT(1) 的精度?
 • CHAR(4) 占用的空间?
 • VARCHAR(255)和VARCHAR(256) 占用的空间?
 • TINYTEXT最大支持的字符数?
 • TIMESTAMP值的范围?
 • …...
列设计原则(1)


 « 每个字段尽可能设置DEFAULT值;
 « 尽可能使用数值型存储,如IP地址;
 « 数值类型定义时声明UNSIGNED;
 « 主键(自增列)使用INT类型;
 « 日期和时间使用TIMESTAMP类型;
 « 尽量不使TEXT/BLOB字段,如有可拆分成行处理;
 « 列名不要与系统保留关键字冲突,如time,date等;

 核心:遵循够用就好的原则;
列设计原则(2)


 BAD DESIGN:
  ID BIGINT AUTO_INCREMENT
  CHAR(10) DEFAULT NULL
  NOT NULL DEFAULT ‘’
  `CREATE_DATE` timestamp NOT NULL default CURRENT_TIMESTAMP
    on update CURRENT_TIMESTAMP
  `LAST_UPDATE_DATE` timestamp NOT NULL default ‘0000-00-00
    00:00:00’
  ……
索引:查询语句的关键因素



     核心:HOW、WHY、 WHEN
快递员的烦恼




         要向5号楼的702和9号楼的501发快
         递,怎么办?
快递员的烦恼(2)




        要是有个楼层图就好了!
索引的类型


InnoDB引擎支持的索引:
• 单列索引
• 主键/唯一索引
• 复合索引
• 前缀索引
InnoDB索引结构
可能用到索引的操作


•   查询语句中有WHERE条件;
•   多表关联查询;
•   执行MIN()、MAX()类型聚集函数;
•   执行ORDER BY对结果集排序;
•   查询的列本身就在索引内;

提示:当存在多个可用的索引时,MySQL会选择最小的那个;
索引的特点


优点:
• 提高查询速度
• 提高内存使用效率

缺点:
• 降低写效率
• 占用更多磁盘空间
不是所有情形都适合使用索引




什么情况下   不用索引 效果更佳?
索引要点
索引不是越多越好
» 表中必须创建 主键,主键应尽可能的短小
» 索引键长度不要超过30字节
» “WHERE”用不到的列不建索引
» 非特殊条件、STATUS/SEX等低异相值列不建索引
» “NULL”列不建索引
» 查询条件有多列时尽可能创建复合索引
BAD-DESIGN 找问题


 CREATE TABLE `xxx_xxxx` (
   `uid` bigint(20) NOT NULL COMMENT '主站用户id ',
   `useriden` char(17) DEFAULT NULL COMMENT '用户uiden',
   `username` char(64) DEFAULT NULL COMMENT '用户名 ',
   `regdate` int(10) DEFAULT NULL COMMENT '注册时间',
   `password` char(32) DEFAULT NULL COMMENT '密码',
   `email` char(255) DEFAULT NULL COMMENT 'email 依赖',
   `status` tinyint(1) DEFAULT NULL COMMENT '0冻结;1正常',
   `image` char(255) DEFAULT NULL COMMENT '头像 ',
   `bigimage` varchar(255) NOT NULL,
   `regip` char(15) DEFAULT NULL COMMENT '注册IP ',
   `lastvisit` int(10) DEFAULT NULL COMMENT '最后访问时间',
   `lastip` char(15) DEFAULT NULL COMMENT '最后访问IP',
   `loginstatus` tinyint(1) NOT NULL DEFAULT '0' COMMENT '登录状态',
   `cas_ticket` varchar(255) NOT NULL COMMENT '登录校验ticket',
   `is_super_admin` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否是超级管理员',
   `type` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1普通用户、2普通行家',
   PRIMARY KEY (`uid`),
   KEY `loginstatus` (`loginstatus`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表'
?
    这只是开始...
    细节并未完全呈现!
与性能密切 关联 的话题


» 执行计划

» 慢查询日志

» 查询缓存

» 语句改写

» ……
您的消息是什么?
Q&A

Oracle&mysql数据库模式设计