前面,我们在表层面对数据库调优做了一些介绍,包括查询优化,索引优化等,本章将探讨数据库的其它调优策略。文章课程链接:MySQL数据库教程天花板,mysql安装到…
1、选择合适的DBMS
简单的讲,要根据自己的系统及业务情况选择好数据库,如果对安全性要求高,可能要使用收费的oracle,选择关系型数据库还是非关系型,选择数据库的哪个存储引擎等等。
2、优化表结构
(1)尽量的遵循三范式
(2)如果经常查询,可以采用冗余字段方式提高效率
(3)对字段类型的选择要合理得当,能使用数值型就不要采用字符型
3、优化逻辑查询
小表驱动大表等,选择既能满足业务需求,效率尽量高的查询
4、优化物理查询
确定逻辑优化后,采用物理优化技术优化(比如索引等)。
5、库级优化
读写分离:用主数据库(master)完成写操作,从数据库(slave)完成读操作,实际运用中可以使用Mycat插件实现
数据分片:数据量非常大(千万级别时),考虑将数据库分成多份,比如 垂直拆分(分库),水平拆分(分表),垂直+水平拆分(分库分表)
优化MySQL服务器主要从两个方面来优化,一方面是对硬件进行优化;另一方面是对MySQL 服务的参数 进行优化。这部分的内容需要较全面的知识,一般只有 专业的数据库管理员 才能进行这一类的优化。
通过优化MySQL的参数可以提高资源利用率,从而达到提高MySQL服务器性能的目的。
MySQL服务的配置参数都在my.cnf 或者my.ini 文件的[mysqld]组中。配置完参数以后,需要重新启动MySQL服务才会生效。
下面对几个对性能影响比较大的参数进行详细介绍。
innodb_buffer_pool_size: 这个参数是Mysgl数据库最重要的参数之一,表示lnnoDB类型的表和索引的最大缓存。它不仅仅缓存索引数据,还会缓存 表的数据。这个值越大,查询的速度就会越快。但是这个值太大会影响操作系统的性能。
key_buffer_size: 表示索引缓冲区的大小。索引缓冲区是所有的线程共享。增加索引缓冲区可以得到更好处理的索引(对所有读和多重写)。当然,这个值不是越大越好,它的大小取决于内存的大小。如果这个值太大,就会导致操作系统频繁换页,也会降低系统性能。对于内存在 4GB 左右的服务器该参数可设置为 256M或384M。
table_cache: 表示同时打开的表的个数。这个值越大,能够同时打开的表的个数越多。物理内存越大,设置就越大。默认为2402,调到512-1024最佳。这个值不是越大越好,因为同时打开的表太多会影响操作系统的性能。
其他还包括:
query_cache_size:表示查询缓冲区的大小。
query_cache_type:的值是o时,所有的查询都不使用查询缓存区。
sort_buffer_sizer:表示每个需要进行排序的线程分配的缓冲区的大小。
join_buffer_size = 8M: 表示联合查询操作所能使用的缓冲区大小,和sort_buffer_size一样。
read_buffer_size:表示 每个线程连续扫描时为扫描的每个表分配的缓冲区的大小(字节) 。
innodb_flush_log_at_trx_commit:表示何时将缓冲区的数据写入日志文件,并且将日志文件写入磁盘中。该参数对于innoDB引擎非常重要。该参数有3个值,分别为0、1和2。该参数的默认值为1。
剩下的自行查询资料了 -_-
一个好的 数据库设计方案 对于数据库的性能常常会起到 事半功倍 的效果。合理的数据库结构不仅可以使数据库占用更小的磁盘空间,而且能够使查询速度更快。数据库结构的设计需要考虑 数据冗余、 查询和更新的速度、字段的数据类型 是否合理等多方面的内容。
拆分表的思路是,把1个包含很多字段的表拆分成2个或者多个相对较小的表。这样做的原因是,这些表中某些字段的操作频率很高(热数据),经常要进行查询或者更新操作,而另外一些字段的使用频率却很低(冷数据 ),冷热数据分离,可以减小表的宽度。如果放在一个表里面,每次查询都要读取大记录,会消耗较多的资源。
MySQL限制每个表最多存储 4096列,并且每一行数据的大小不能超过 65535字节。表越宽,把表装载进内存缓冲池时所占用的内存也就越大,也会消耗更多的IO。 冷热数据分离的目的是:
1、减少磁IO,保证热数据的内存缓存命中率。
2、更有效的利用缓存,避免读入无用的冷数据。
对于需要经常联合查询的表,可以建立中间表以提高查询效率。通过建立中间表,把需要经常联合查询的数据插入中间表中,然后将原来的联合查询改为对中间表的查询,以此来提高查询效率,但要考虑维护的成本(数据一致性)。
虽然要尽可能的遵守范式,但技术是为业务服务的,我们可以根据业务情况,适当的增加冗余字段,以此提高查询效率,比如对于订单表,是需要显示商品名称及其图片的,我们可以将这两个字段冗余,而不再去关联查询,其次,对于订单收货信息等,这类字段需要冗余,因为用户可以修改收货信息的数据,一旦修改,在只关联收货地址id的情况下,数据也会跟着变,不符合场景,实际应该记录的是当时用户下单的地址。
优先选择符合存储要求的最小的数据类型,比如人的年龄,tinyint就能存下,就不要用其他的了,数据小对于索引来讲也是有好处的。其次,也要避免使用 TEXT、BLOB、ENUM 等数据类型。
插入记录时,影响插入速度的主要是索引、唯一性校验、一次插入记录条数等。根据这些情况可以分别进行优化。这里我们分为MyISAM引|擎和InnoDB存储引擎来讲。
1、MyISAM引擎的表
(1)禁用索引
对于非空表,插入记录时,MySQL会根据表的索引对插入的记录建立索引。如果插入大量数据,建立索引就会降低插入记录的速度。为了解决这种情况,可以在插入记录之前禁用索引,数据插入完毕后再开启索引。
(2)禁用唯一性校验
(3)使用批量插入
2、InnoDB引擎的表
(1)禁用唯一性检查
插入数据之前执行 set unique_checks=0 来禁止对唯一索引的检查,数据导入完成之后再运行 setunique_checks=1。这个和MyISAM引擎的使用方法一样。或者我们可以在业务层面去检查。
(2)禁用外键检查
插入数据之前执行禁止对外键的检查,数据插入完成之后再恢复对外键的检查。
(3)禁止自动提交
插入数据之前禁止事务的自动提交,数据导入完成之后,执行恢复自动提交操作。
在设计字段的时候,如果业务允许,建议尽量使用非空约束。
这样做的好处是:
1、进行比较和计算时,省去要对NULL值的字段判断是否为空的开销,提高存储效率。
2、非空字段也容易创建索引。因为索引NULL列需要额外的空间来保存,所以要占用更多的空间。使用非空约束,就可以节省存储空间 (每个字段1个bit)。
MysQL提供了分析表、检查表和优化表的语句。分析表主要是分析关键字的分布,检查表主要是检查表是否存在错误,优化表主要是消除删除或者更新造成的空间浪费。
具体使用可以查阅相关资料
当MySQL单表记录数过大时,数据库的CRUD性能会明显下降,可以采取以下措施优化:
禁止不带任何限制数据范围条件的查询语句。其次,对于一些支付交易数据,只允许查询一年以内的数据,一年以上需要申请,然后在查询。对于订单数据也可以限制时间,但我看了淘宝,最开始的订单都是能查到的(毕竟人家是顶级大厂*_*)
如果我们的数据量达到千万级别时,对数据库的性能是一种考验,我们可以考虑垂直分库,将关联的数据库表部署在同一个数据库上
如果数据表中的列过多,且有些列不经常使用,我们可以采用垂直分表的方式,将表分为两份,不常用的字段单独放一份,需要的时候去关联查就行
垂直拆分的优点: 可以使得列数据变小,在查询时减少读取的Block数,减少IO次数,此外,垂直分区可以简化表的结构,易于维护。
**垂直拆分的缺点:**主键会出现冗余,需要管理冗余列,并会引起 JOIN 操作。此外,垂直拆分会让事务变得更复杂。
尽量控制单表数据量的大小,建议控制在 1000万以内。1000万并不是MySQL数据库的限制,过大会造成修改表结构、备份、恢复都会有很大的问题。此时可以用 历史数据归档 (应用于日志数据), 水平分表 (应用于业务数据)等手段来控制数据量大小。 I
这里我们主要考虑业务数据的水平分表策略。将大的数据表按照 某个属性维度 分拆成不同的小表,每张小表保持相同的表结构。比如你可以按照年份来划分,把不同年份的数据放到不同的数据表中。2017 年、2018 年和 2019 年的数据就可以分别放到三张数据表中。
水平分表仅是解决了单一表数据过大的问题,但由于表的数据还是在同一台机器上,其实对于提升MVSOL并发能力没有什么意义,所以水平拆分最好分库 ,从而达到分布式的目的。
水平拆分能够支持非常大的数据量存储,应用改造也少,但分片事务难以解决,跨节点Join性能较差,逻辑复杂,因此,建议尽量不要对数据进行分片。
数据库分片的两种常见方案
客户端代理:分片逻辑在应用端,封装在jar包中,通过修改或者封装JDBC层来实现。 当当网的 ShardingJDBC 、阿里的TDDL是两种比较常用的实现。
中间件代理:在应用和数据中间加了一个代理层。分片逻辑统一维护在中间件服务中。我们现在谈的 Mycat、360的Atlas、网易的DDB等等都是这种架构的实现。
在MySQL 8.0中可以设置 服务器语句超时的限制,单位可以达到 毫秒级别。当中断的执行语句超过设置的毫秒数后,服务器将终止查询影响不大的事务或连接,然后将错误报给客户端。
设置服务器语句超时的限制,可以通过设置系统变量 MAX_EXECUTION_TIME 来实现。默认情况下MAX_EXECUTION_TIME的值为0,代表没有时间限制。
MVSOL 8.0使用CREATE TABLESPACE 语句来创建一个全局通用表空间。全局表空间可以被所有的数据库的表共享,而且相比于独享表空间,使用手动创建共享表空间可以节约元数据方面的内存。可以在创建表的时候,指定属于哪个表空间,也可以对已有表进行表空间修改等。
不可见索引的特性对于性能调试非常有用。在MySQL 8.0中,索引可以被“隐藏”和“显示”。当一个索引被隐藏时它不会被查询优化器所使用。也就是说,管理员可以隐藏一个索引,然后观察对数据库的影响。如果数据库性能有所下降,就说明这个索引是有用的,于是将其“恢复显示”即可,如果数据库性能看不出变化,就说明这个索引是多余的,可以删掉了。
需要注意的是当索引被隐藏时,它的内容仍然是和正常索引一样实时更新的。如果一个索引需要长期被隐藏,那么可以将其删除,因为索引的存在会影响插入、更新和删除的性能。
数据表中的主键不能被设置为invisible。
如果总结的还行,就点个赞呗 @_@ 如有错误,欢迎指正!