MySQL优化五(Schema和Query的优化)

MySQL部分已经陆陆续续写到第五个章节了。MySQL的学习笔记大都是根据几本关于MySQL的书籍,还有一些网络上的资源,以及其他同行们的学习经验。技术的进步离不开书籍,很巧,技术的拼音正好是书籍拼音反过来写, shuji 和 jishu,感觉自己好无聊。。。

到了第五个章节,还是继续把记录下的东西进行理论的总结,既然这么说,那么特别的例子不会给出,这个还是放在以后按照实例来记录吧,这也是为了自己履行温故而知新的学习方法而做的特别的安排,对于大部分的知识点,最好的方式是自己动手做,然而,必要的基础知识又必不可少,因此,为了强迫自己能非常扎实的掌握技术知识,采取了一些奇怪的方式。

譬如看书的时候,记忆目录,浏览内容,画出重点,实际用到的时候,再深入,记录经典案例,写总结的时候,却分开写,果真是对付懒人的办法啊。

废话这么多,开始吧。。。

Schema

数据库范式

70年代的数据库范式,确实是具有指导地位的,当年无论是学生时期,还是自学甚至自己动手做的时候,都是以范式为主导,设计出的结构,清清楚楚,非常漂亮,基本没有冗余字段。

但是发展到现今,真实世界的各种另类需求,造就了反范式的设计思想,对于反范式,个人理解为就是空间换取时间。正是这点,就是可以利用冗余,来提高数据库的性能,增加了维护冗余的某些成本,但是提高了业务逻辑的响应。

举个简单的栗子,很多网站都有排行列表,通常都是周排行,月排行等,完全可以做成冗余表,而避免区查询主表。

数据类型

在设计数据库结构是,必须废除清楚各种数据类型的特性,特别是某些比较重要的字段。

整型
有好几种,首先清楚他们的存储长度,最大和最小值,这里的最大最小跟有无符号也有关系
比如总是将主键设置为无符号,那么,最大值会更大,毕竟负数的主键用不着。
一些MySQL工具中要你填写TinyInt时,其实是要你填写它的显示长度,而非长度。

浮点型
Float 是不精确的,Double更好点
更有甚之,把浮点的2个部分,做成2个整型的字段,以表示更精确,或者,更符合特别的需求。

时间类型
多数用Unix时间戳,不过据说时间格式已经优化得很好了,可以使用datetime之类的,只是要注意时区问题,来选择更好的。

文本型
text的无法做索引,注意char和varchar的区别

对于所有的类型,除了无法做默认值的字段,都应该在数据层面上设定默认值,因为NULL类型在搜索时是会影响性能的。

减少join

减少Join其实是可以使用冗余来解决,在某些情况下,如果数据量特别大,那么单表操作肯定比join表操作要性能上消耗少。

表的拆分

OO里面有个对象关系的概念,一对一。一个对象对应另外存在另外一个对象,依赖或者聚合。其实数据库里面也可以如此做,但是本博要说的概念其实被偷换了,准确来说是表的垂直拆分。

举个栗子,一个表中,有一定数量的字段,但是某些场景,频繁读取其中一部分字段,比如30%的字段,其余的在另一个场景中需要频繁入库, 比如70%的字段, 那么分开吧。

一方面,保持2个表的关系,其实逻辑上只有一张表,保持逻辑统一。另一方面,操作是分开的,I/O的压力被分开了,甚至于分成两个数据库服务器。

水平拆分

某些场景下,并不是字段太多,而是记录数太多,而这个记录数非常巧的因为某个字段或某些字段的内容上分别适用于不同场景。

举个栗子,某个字段,譬如身份证,可以按照身份证开头几位,辨别出是哪个地区,而恰巧,某个场景就是通过地区来操作身份证,并且读取又非常之频繁,那么,根据身份证这个特定字段,进行表内容的水平拆分,按照地区的不同数据量进行划分,划分为几个不同地区的组合,而这些组合的总记录数和读取量又差不多,那恰好做成不同的表,根据不同应用场景来进行操作。

Query

索引

索引的本质是B+树的查询,简单来说,对于某一字段,或者某几个字段进行排序,方便查找,好比很多技术书籍都会有个索引之类的,使用字母表进行排序,方便查找。

另外,索引是基于原表而建立的,因此,索引肯定会影响入库的操作,比如一个表有N个索引,那么在入库时,这N个索引牵涉到的字段,必须重新排一下序,就是说索引需要rebuild一下,可想而知需要需要牺牲的这些时间。当然,可以用其他方式来减少这些损失,以达到更快的响应,例如,分库。

数据类型

某些数据类型不适合建立索引,整型就比较适合。

字符型不大好。

字段中出现NULL,更不好,就是上文所说的,最好字段都有默认值的原因。

索引使用

索引和 WHERE 子句关系很密切,以下是一些tips

-不使用 != ,这个会让索引失效

-WHERE 子句中,被索引的字段的位置很重要,例如 WHERE A=x AND B=y, 那么有效索引是 A,A+B,以B开头的,是无效的

-MySQL函数如果被使用在WHERE 中是,索引无效

-使用LIKE,模糊匹配在前面,是无效的,例如 ‘%abc’

-尽量不要使用 SELECT *

-查询一条记录时,使用LIMIT 1

-索引是放在内存的,因此配置MySQL的时候,相关的buffer 和 cache 放放大

了解了索引,就可以很好的利用它,以上是一些是整理的小思路,至于何时使用索引,如何使用将在下一个笔记章节中整理。