@yangxitian
2016-05-04T08:17:38.000000Z
字数 4207
阅读 2122
blog
By Shelter. 2016/3/29
一般使用utf8字符集,utf8_general_ci排序规则。
每种字符集都会有相应的排序规则。
utf8_general_ci校对速度快,但准确度稍差。
utf8_unicode_ci准确度高,但校对速度稍慢。
utf8_unicode_ci和utf8_general_ci对中、英文来说没有实质的差别。
如果你的应用有德语、法语或者俄语,请一定使用utf8_unicode_ci。一般用utf8_general_ci就够了,到现在也没发现问题。。。
存储引擎说白了就是如何存储数据、如何为存储的数据建立索引和如何更新、查询数据等技术的实现方法。因为在关系数据库中数据的存储是以表的形式存储的,所以存储引擎也可以称为表类型(即存储和操作此表的类型)。
在Oracle 和SQLServer等数据库中只有一种存储引擎,所有数据存储管理机制都是一样的。而MySql数据库提供了多种存储引擎。用户可以根据不同的需求为数据表选择不同的存储引擎,用户也可以根据自己的需要编写自己的存储引擎。
这里就只介绍常用的储存引擎:
笔者认为,MYISAM和InnoDB的选择,主要考虑是否需要支持事务即可,因为现在硬件都很发达了,内存不是什么问题。需要事务的,采用InnoDB,否则采用MYISAM。
数据类型有很多,谷歌可以搜到很多,这里就不多说。常用的有:
类型 | 说明 |
---|---|
tinyint(m) | 1个字节 范围(-128~127)。m指显示长度 |
int(m) | 4个字节 范围(-2147483648~2147483647)。m指显示长度 |
char(n) | 长度n,字符长度,最长255. |
varchar(n) | 长度n,字符长度, 最长65535. |
tinytext | 可变长度,最多255. |
text | 可变长度,最多65535. |
mediumtext | 可变长度,最多2^24-1. |
longtext | 可变长度,最多2^32-1. |
char和varchar区别:
1.char类型的字符串检索速度要比varchar类型的快。
2.请参考MySQL数据库中CHAR与VARCHAR之争
3.个人总结:
长度不是经常改变:长度确定char(用户名)/长度不确定varchar(qq空间说说)
长度经常改变:char (qq个性签名)varchar和text区别:
1.varchar可指定n,text不能指定,内部存储varchar是存入的实际字符数+1个字节(n<=255)或2个字节(n>255),text是实际字符数+2个字节。
2.text类型不能有默认值。
3.varchar可直接创建索引,text创建索引要指定前多少个字符。varchar查询速度快于text,在都创建索引的情况下,text的索引效果不明显。
系统读取mysql数据的时候,是强行统一成小写的。
所以 数据库名,表名,字段名 都采用下划线分割法。
首先,要先理解什么是三种范式。让我们来举个例子。
假设我们现在要设计一个书籍管理系统。
name | pubName | year | author1 | author2 |
---|---|---|---|---|
mysql5权威指南 | 人民电邮出版社 | 2009 | Mk | DS |
linux私房菜 | 清华大学出版社 | 2011 | 鸟哥 | |
php精粹 | 机械工程出版社 | 2012 | 鸟哥 | DS |
问题来了,假设有一本书有三个作者呢?
根据范式优化如下:
第一范式
id | name | pubName | year | author |
---|---|---|---|---|
1 | mysql5权威指南 | 人民电邮出版社 | 2009 | Mk |
2 | mysql5权威指南 | 人民电邮出版社 | 2009 | DS |
3 | linux私房菜 | 清华大学出版社 | 2011 | 鸟哥 |
4 | php精粹 | 机械工程出版社 | 2012 | 鸟哥 |
5 | php精粹 | 机械工程出版社 | 2012 | DS |
这样子的话,就能自由添加书籍了。但是还是存在很多冗余的数据,占据内存。
第二范式
book表
id | name | year | pubName |
---|---|---|---|
1 | mysql5权威指南 | 2009 | 人民电邮出版社 |
2 | linux私房菜 | 2011 | 清华大学出版社 |
3 | php精粹 | 2012 | 机械工程出版社 |
author表
id | name |
---|---|
1 | Mk |
2 | DS |
3 | 鸟哥 |
book_author表
id | book_id | author_id |
---|---|---|
1 | 1 | 1 |
2 | 1 | 2 |
3 | 2 | 3 |
4 | 3 | 3 |
5 | 3 | 2 |
明显数据冗余性大大降低,扩展性都得到了很大的提升。
第三范式
book表
id | name | year | pub_id |
---|---|---|---|
1 | mysql5权威指南 | 2009 | 1 |
2 | linux私房菜 | 2011 | 2 |
3 | php精粹 | 2012 | 3 |
publish表
id | name |
---|---|
1 | 人民电邮出版社 |
2 | 清华大学出版社 |
3 | 机械工程出版社 |
什么?没看懂?没关系,有另一种思维。
关系 | 处理 |
---|---|
一对多 | 外键解决 |
多对一 | 外键解决 |
多对多 | 中间表解决 |
上面中,book 和 出版社publish 就算是多对一,换位思考就是一对多了。
而book 和 author 就算是多对多关系。靠book_author中间表来解决。
是不是简单粗暴?
参考YY哥-索引与优化
(此文中提到用内置日期类型储存时间,笔者认为用整型储存时间戳来储存时间 无论是从排序,读取效率或者前端显示自由度来看,都是是最为科学的。)
索引是提升速率的一个好途径。在经常需要where到的字段,可以添加索引。
速度比较:唯一索引 > 普通索引
(主索引和唯一索引唯一的区别就是使用的关键字为PRIMARY而不是UNIQUE)
另外,索引会导致修改操作变慢。
数据库每次数据修改,都会刷新索引表。批量修改的时候,可以使用DELAY_KEY_WRITE——批量修改完毕后,再刷新。
DELAY_KEY_WRITE的详细说明
另外,如果经常需要到 WHERE field1 = xx AND field2 = xx 查询,可以建立组合索引。
限制:
另外,尽量避免NULL:应该指定列为NOT NULL,除非你想存储NULL。在MySQL中,含有空值的列很难进行查询优化,因为它们使得索引、索引的统计信息以及比较运算更加复杂。应该用0、一个特殊的值或者一个空串代替空值。
这个或许设计里比较难的一个了!
100%根据范式来,是可以,但是在代码逻辑层会比较麻烦。有时候处理起来,反而效率变低了。
因此,一定程度上的数据冗余是允许的。或者通过一些技巧来降低代码层的复杂性。好比:
book表
id | name | year | pubName | author_ids |
---|---|---|---|---|
1 | mysql5权威指南 | 2009 | 人民电邮出版社 | 1-2 |
2 | linux私房菜 | 2011 | 清华大学出版社 | 3 |
3 | php精粹 | 2012 | 机械工程出版社 | 3-2 |
这样子,就少了一张中间表。不过要注意考虑项目的扩展性,或者以后客户会有什么坑爹的需求,不然后期可能会是一个大坑!
场景是这样子的:
id | account | password | role | id_card | student_card |
---|---|---|---|---|---|
1 | student1 | 123 | STUDENT | null | 123456 |
2 | teacher1 | 123 | TEACHER | 56789 | null |
教室有自己的特有字段(id_card),学生有自己的特有字段(student_card)。那么就造成了一些数据库内存浪费。
解决方法之一就是垂直切分:
user表
id | account | password | role |
---|---|---|---|
1 | student1 | 123 | STUDENT |
2 | teacher1 | 123 | TEACHER |
student表
user_id | id_card |
---|---|
1 | 123456 |
teacher表
user_id | student_card |
---|---|
2 | 56789 |
还有一种解决方式就是直接拆分成 teacher 和 student 表,这样子代码层就变得很简单。不过登陆注册等就需要分角色操作。具体看业务需求吧!
说数据库是一门艺术完全不为过,只有多实践,才能逐渐看的远吧!