mysql笔记01 MySQL架构与历史、Schema与数据类型优化

MySQL架构与历史html

1. MySQL架构推荐参考:http://www.cnblogs.com/baochuan/archive/2012/03/15/2397536.html数据库

2. MySQL会解析查询,并建立内部数据结构(解析树),而后对其进行各类优化,包括重写查询、决定表的读取顺序,以及选择合适的索引等。用户能够经过特殊的关键字提示(hint)优化器,影响它的决策过程。缓存

    也能够请求优化器解释(explain)优化过程的各个因素,使用户能够知道服务器如何进行优化决策的,并提供一个参考基准,便于用户重构查询和schema、修改相关配置,使应用尽量高效运行。安全

3. 对于SELECT语句,在解析查询以前,服务器先检查查询缓存(Query Cache),若是可以在其中找到对应的查询,服务器就不会再执行查询解析、优化和执行的整个过程,而是直接返回查询缓存中的结果集。服务器

4. 读锁(共享锁)是共享的,或者说是互相不阻塞的。多个客户在同一时刻能够同时读取同一个资源,而互不干扰。数据结构

    写锁(排他锁)则是排他的,也就是说一个写锁会阻塞其余的写锁和读锁,这是出于安全策略的考虑,只有这样才能确保在给定的时间里,只有一个用户能执行写入,并防止其余用户读取正在写入的同一资源。架构

5. 锁粒度:锁的各类操做,包括得到锁、检查锁是否已经解除、释放锁等,都会增长系统的开销。若是系统花费大量的时间来管理锁,而不是存储数据,那么系统性能可能会受到影响。并发

    锁策略:就是在锁的开销和数据安全性之间寻求平衡。框架

    表锁(table lock):表锁是MySQL中最基本的锁策略,而且是开销最小的锁策略。写锁比读锁有更高的优先级,所以一个写锁请求可能会被插入到读锁队列的前面(写锁能够插入到锁队列中读锁的前面,反之ide

                               读锁则不能插入到写锁的前面)。

    行级锁(row lock):行级锁能够最大程度地支持并发处理(同时也会带来最大化的锁开销)。

6. 事务:事务就是一组原子性的SQL查询,或者说一个独立的工做单元。事务内的语句,要么所有执行成功,要么所有执行失败。

    1). ACID:

          原子性(atomicity):一个事务必须视为一个不可分割的最小工做单元,整个事务中全部操做要么所有提交成功,要么所有失败回滚,对于一个事务来讲,不可能只执行其中的一部分操做,这就是事务的原子性。

         一致性(consistency): 数据库老是从一个一致性状态转换到另外一个一致性状态。

         隔离性(isolation):一般来讲,一个事务所作的修改在最终提交之前,对其余事务老是不可见的。

         持久性(durability):一旦事务提交,则其所作的修改就会永久保存到数据库中。此时,即便系统崩溃,修改的数据也不会丢失。

   2). 事务处理过程当中额外的安全性,也会须要数据库系统作更多的额外工做,影响运行效率。

   3). 隔离级别:

        READ UNCOMMITTED(未提交读):事务能够读取未提交的数据,这也被称为脏读(Dirty Read)

        READ COMMITTED(提交读):大多数数据库的默认隔离级别,但MySQL不是。这个级别有时候也叫不可重复读,由于两次执行一样的查询,可能会获得不同的结果。

                                                是指在一个事务内,屡次读同一数据。在这个事务尚未结束时,另一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,因为第二个事务的修改,

                                                那么第一个事务两次读到的的数据多是不同的。这样就发生了在一个事务内两次读到的数据是不同的,所以称为是不可重复读。

        REPEATABLE READ(可重复读):解决了脏读问题。该级别保证了同一个事务中屡次读取一样记录的结果是一致的。MySQL的默认隔离级别。

        SERIALIZABLE(可串行化):最高隔离级别,经过强制事务串行执行,避免了前面说的幻读问题。只有在数据很是中的时候才使用。

   4). 死锁:指两个或多个事务在同一资源上相互占用,并请求锁定对方占用的资源,从而致使恶性循环的现象。当多个事务试图以不一样的顺序锁定资源时,就可能会产生死锁。

        InnoDB目前处理死锁的方法是,将持有最少行级排他锁的事务进行回滚。

   5). 使用事务日志,存储引擎在修改表的数据时,只须要修改其内存拷贝,再把修改行为记录到持久在硬盘的事务日志中,而不用每次都将修改的数据自己持久到硬盘。事务采用的是追加的方式。事务日志持久化

         之后,内存中被修改的数据在后台能够慢慢地刷回到磁盘。若是数据的日志已经记录到事务日志并持久化,但数据自己尚未回写磁盘,此时系统崩溃,存储引擎在重启时可以自动恢复这部分修改的数据。

   6). MySQL中的事务:

         a. 自动提交(AUTOMCOMMIT):MySQL默认采用自动提交的模式。也就是说若是不是显示地开始一个事务,则每一个查询都会被当作一个事务执行提交操做。能够经过设置AUTOCOMMIT变量来启用或禁用

             自动提交模式。另外,有一些命令执行以前会强制执行COMMIT提交当前的活动事务。

         b. 隐式和显示锁定:事务执行过程当中,随时均可以执行锁定,锁只有在执行COMMIT或者ROLLBACK的时候才会释放,而且全部的锁是在同一时刻被释放。这些都是隐式锁。

7. MySQL的大多数事务型存储引擎实现的都不是简单的行级锁。基于提高并发性能的考虑,它们通常都同时实现了多个版本并发控制(MVCC, Multi-Version Concurrency Control)。能够认为MVCC是行级锁的一个变种,可是它在不少状况下避免了

    加锁操做,所以开销更低。MVCC的实现,经过保存数据在某个时间点的快照来实现的。

8. 在文件系统中,MySQL将每一个数据库(也能够称为schema)保存为数据目录下的一个子目录。建立表时,MySQL会在数据库子目录下建立一个和表同名的.frm文件保存表的定义。例如:MyTable表,对应

    MyTable.frm文件。

9. MySQL在5.5之后才完全使用InnoDB plugin替代旧版本的InnoDB。做为事务型存储引擎,InnoDB经过一些机制和工具支持真正的热备份,Oracle提供的MySQL Enterpries Backup 、Percona提供开源的

    XtraBackup均可以作到这一点。MySQL的其余存储引擎不支持热备份,要获取一致性视图须要中止对全部表的写入,而在读写混合场景中,中止写入可能也意味着中止读取。

 

 

Schema与数据类型优化

1. 选择优化的数据类型

    1). 更小的一般更好:更小的数据类型一般更快,由于他们占用更少的磁盘、内存和CPU缓存,而且处理须要的CPU周期也更少。

    2). 简单就好:简单的数据类型的操做一般须要更少的CPU周期。例如:整型比字符串操做的代价更低,由于字符集和校对规则(排序规则)是字符串比较比整型比较更复杂。这里有两个例子:

                       一个是应该使用MySQL内建的类型而不是字符串来存储日期和时间,另一个是应该使用整型存储IP地址。

    3). 避免使用null:一般状况下最好指定列为not null,除非真的须要存储null。由于null列使得索引、索引统计和值比较都更复杂。可为null的列会使用更多的存储空间,在MySQL中也须要特殊处理。

2. MySQL兼容性支持不少别名,例如INTEGER、BOOL等。他们都是别名,这些别名可能使人不解,但不会影响性能。若是建表时采用数据烈性的别名,而后用show create table检查,会发现MySQL

    报告的是基本类型,而不是别名。

3. 整数类型:TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,分别使用8,16,24,32,64位存储空间。它们的存储值的范围从-2的n-1次幂,到2的n-1次幂减一。

    1). 整数类型有可选的UNSIGNED属性,表示不容许负值,这大体可使正数的上限提升一倍。

    2). 有符号和无符号类型使用相同的存储空间,而且有相同的性能,所以能够根据实际状况选择合适的类型。

    3). MySQL能够为正数类型指定宽度,例如INT(11),但大多数应用这是没有意义的。对于存储和计算来讲,INT(1)和INT(20)是相同的。

4. 实数类型:实数是带有小数部分的数字。然而,它们不仅是为了存储小数部分;也可使用DECIMAL存储比BIGINT还大的整数。

    1). FLOAT和DOUBLE类型支持使用标准的浮点运算进行近视计算DECIMAL类型用于存储精确的小数。

    2). 浮点类型在存储一样类型的范围的值时,一般比DECIMAL使用更少的空间。FLOAT使用4个字节存储.DOUBLE占用8个字节,相比FLOAT有更高的精度和更大的范围。

    3). 由于须要额外的空间和计算开销,因此应该尽可能只在对小数进行精确计算时才使用DECIMAL。在数据量比较大的时候,能够考虑使用BIGINT代替DECIMAL,将对应的值扩大N倍。

5. 字符串类型:

    1). VARCHAR:它比定长类型更节省空间,由于它仅使用必要的空间。VARCHAR节省了空间,因此对性能也有帮助。可是因为行是变长的,在UPDATE时可能使行变得比原来更长,这就致使须要作额外的工做。

         下面的状况使用VARCHAR是合适的:字符串最大长度比平均长度大不少;列的更新少,因此碎片不是问题;使用了像UTF-8这样复杂的字符集,每一个字符使用不一样的字节数。

         在5.0或更高的版本中,MySQL在存储和检索时会保留末尾空格。InnoDB则更灵活,它能够把长的VARCHAR存储为BLOB。

    2). CHAR: 定长,当存储CHAR值时,MySQL会删除全部的末尾空格。定长的CHAR类型不容易产生碎片,对于很是短的列,CHAR比VARCHAR在存储空间上也更有效率,VACHAR还有一个记录长度的额外字节。

    3). 记住字符串的长度定义不是字节数,是字符数。多字节字符集会须要更多的空间存储单个字符。

    4). 与CHAR和VARCHAR相似的类型还有BINARY和VARBINARY,它们存储的是二进制字符串。二进制字符串中存储的是字节码而不是字符。

         二进制比较的优点并不只仅体如今大小写敏感上。MySQL比较BINARY字符串是,每次按一个字节,而且根据该字节的数值进行比较。所以,二进制比字符比较简单的多,因此也就更快。

    5). BLOB和TEXT类型:BLOB和TEXT都是为了存储很大的数据而设计的字符串数据类型,分别采用二进制和字符方式存储。当BLOB和TEXT值太大时,InnoDB会使用专门的"外部"存储区域来进行存储。原表字段

          存储指针指向外部存储区域。

6. 日期和时间类型:MySQL能存储的最小时间粒度为秒。

    1). DATETIME : 这个类型能保存大范围的值,从1001年到9999年,精度为秒。它把日期和时间封装到格式为YYYYMMDDHHMMSS的整数中。默认显示格式为"2008-02-16 22:37:08"

    2). TIMESTAMP:保存从1970年1月1日午夜依赖的秒数,它和UNIX时间戳相同。只能表示从1970年到2038年。TIMESTAMP由于空间占用小,因此效率更高。

    3). 可使用BIGINT类型存储微秒级别的时间戳。

7. 位运算:BIT , SET 

8. 选择标识符(identifier,主键) 

    1). 当选择标识列的类型时,不只仅须要考虑存储类型,还须要考虑MySQL这种类型怎么执行计算和比较

    2). 一旦选择了一种类型,要确保在全部关联表中都使用一样的类型。会用不一样数据类型可能致使性能问题,即便没有性能影响,在比较操做时隐式类型转换也可能致使很难发现错误。

    3). 在能够知足值的范围要求,而且预留将来增加空间的前提下,应该选择最小的数据类型。

    4). 整数类型一般是标识列最好的选择,由于它们很快而且可使用AUTO_INCREMENT

    5). 若是可能,应该避免使用字符串类型做为标识列,由于它们很消耗空间,而且一般比数字类型慢。

    6). 对于彻底"随机"的字符串也须要多加注意。例如:MD5(),SHAI()或者UUID()产生的字符串。这些函数生成的新值也任意分布在很大空间内,这会致使INSERT和一些SELECT语句很缓慢

    7).若是存储UUID值,则应该移除"-"符号,或者更好的作法是,用UNHEX()函数转换UUID值为16字节的数字,并存储在一个BINARY(16)的列中。检索时再转换回来。

9. 小心利用框架自动生成的schema(表)

10. 人们一般使用VARCHAR(15)来存储IP地址。然而,它们实际是32位无符号整数,不是字符串。用小数点将字段分割成四段是为了阅读方便。因此应该用无符号整数存储IP地址。MySQL提供INET_ATON()

      和INET_NTOA()函数在这两种表示方法之间转换。(inet_ntoa(3507806248)  --> 209.20.224.40 )

11. MySQL schema 设计中的陷阱:

      1). 太多的列

      2). 太多的关联

      3). 全能的枚举

      4). 变相的枚举

      5). 非此发明的NULL:不要由于不使用NULL值,而走极端,根据实际状况也可使用NULL

12. 范式的优势和缺点

      优势:

      1). 范式化的更新操做一般比反范式化要快

      2). 修改更少的数据

      3). 范式化的表一般表更小,能够更好地放在内存中,因此执行操做会更快

      缺点:一般须要关联查询,不只代价昂贵,也可能使一些索引策略无效

13. 反范式的优势和缺点:

      优势:很好的避免关联,更有效的使用索引策略

      缺点:范式的优势,就是反范式的缺点

14. 缓存表和汇总表:

     1). 缓存表:存储那些能够比较容易的从schema其余表获取(但每次获取速度缓慢)数据的表

     2). 汇总表:保存的是使用GROUP BY语句聚合数据的表。实时计算统计值是很昂贵的操做。

     4). 在使用缓存表和汇总表时,必须决定是实时维护数据仍是按期重建。哪一个更好依赖于应用程序,可是按期重建并不仅是节省资源,能够保持表不会有不少碎片,以及彻底顺序组织的索引。

15. 影子表:指的是在一张真实表"背后" 建立的表。当完成了建表操做后,能够经过一个原子的重命名操做切换影子表和原表。原表尽可能保留备份,防止新表出问题。

16. 物化视图:物化视图其实是预先计算而且存储在磁盘上的表,能够经过各类各样的策略刷新和更新。MySQL并不原声支持物化视图,可使用开源工具Flexviews。

                    对比传统的维护汇总表和缓存表的方法,Flexviews经过提起对源表的更改,能够增量地从新计算物化视图的内容。

 17. 计数器表:建立一张独立的表存储计数器一般是一个好主意。使用计数器表的一些技巧

       1). 为了防止互斥锁影响效率,能够添加多条记录,随机更新一条记录。统计总数时,将全部数据相加。

       2). 对于须要根据时间更新计数器,也能够用上述方法,不过多加一步操做。天天定时将前一天的总数合计起来,插入到计数器表,删除那些零散的统计记录。

18. 加快ALTER TABLE操做的速度:MySQL的ALTER TABLE操做的性能对大表来讲是一个问题。MySQL执行大部分修改表结构的方法是用新的结构建立一个空表,从旧表中查出全部数据插入新表,而后删除旧表。

      能够经过ALTER COLUMN操做来改变列的默认值。这个语句会直接修改.frm文件而不涉及表数据。因此,这个操做很是快。

  

 

1. 更小的一般更好:更小的数据类型一般更快,由于他们占用更少的磁盘、内存和CPU缓存,而且处理须要的CPU周期也更少。

2. 简单就好:简单的数据类型的操做一般须要更少的CPU周期。例如:整型比字符串操做的代价更低,由于字符集和校对规则(排序规则)是字符串比较比整型比较更复杂。这里有两个例子:

                   一个是应该使用MySQL内建的类型而不是字符串来存储日期和时间,另一个是应该使用整型存储IP地址。

3. 避免使用null:一般状况下最好指定列为not null,除非真的须要存储null。由于null列使得索引、索引统计和值比较都更复杂。可为null的列会使用更多的存储空间,在MySQL中也须要特殊处理。

4. 由于须要额外的空间和计算开销,因此应该尽可能只在对小数进行精确计算时才使用DECIMAL。在数据量比较大的时候,能够考虑使用BIGINT代替DECIMAL,将对应的值扩大N倍。

5. 二进制比较的优点并不只仅体如今大小写敏感上。MySQL比较BINARY字符串是,每次按一个字节,而且根据该字节的数值进行比较。所以,二进制比字符比较简单的多,因此也就更快。

6. 可使用BIGINT类型存储微秒级别的时间戳。

7. 一旦选择了一种类型,要确保在全部关联表中都使用一样的类型。会用不一样数据类型可能致使性能问题,即便没有性能影响,在比较操做时隐式类型转换也可能致使很难发现错误。

8. 若是可能,应该避免使用字符串类型做为标识列,由于它们很消耗空间,而且一般比数字类型慢。

9. 范式(修改多,关联查询少)和反范式(查询多,修改少)的选择

10. 缓存表和汇总表

相关文章
相关标签/搜索