快乐学习
前程无忧、中华英才非你莫属!

想要深度优化MySQL,一篇不得不看的文章.



一、介绍


 在MySQL 8.0中,InnoDB是默认的MySQL存储引擎、它具有高可靠,高性能,通用型的特质。



二、优势

1、 DML操作遵循 ACID模型, 具有 提交回滚 崩溃恢复 功能的事务 以保护用户数据

2、 行级锁定和Oracle风格的一致性读取,可提高多用户并发性和性能。

3、 InnoDB表将数据排列在磁盘上以优化基于主键的查询 每个 InnoDB表都有一个称为聚簇索引的主键索引 ,用于组织数据以最小化主键查找的I / O  ,每个表必须要有显示的设置一个主键才是最好)


4、  InnoDB支持 FOREIGN KEY约束。使用外键,将检查插入,更新和删除,以确保它们不会导致不同表之间的不一致  (这个算不上优势,很多规范是禁止使用外键的,目的是减少数据库

的自我判断,直接粗暴的存取才是最快的。)


三、功能



从这里小编总结,它的核心功能一个是索引、缓存、基于时间点的恢复、MVCC、复制,而这里面除非我们有MySQL源码级别二次开发的能力,可以搞搞MVCC,搞搞复制,可以直接提升MySQL的性能,

而小编属于低级别的使用者只能控制的只能是用什么类型的索引、怎么添加索引、缓存空间给多大,日志备份和管理好之后数据丢失可以基于日志进行时间点的恢复啊,这些途径而已啦,哪天心血来潮,一定甩开膀子调试,吊打mysql源码~。







四、使用innodb表的好处


1、 InnoDB 崩溃恢复会 自动完成在崩溃之前提交的所有更改,并撤消正在进行但未提交的任何更改,无需在重新启动数据库后执行任何特殊操作。


2、 *(缓存) 缓冲池,当数据被访问主内存中缓存表和索引数据。经常使用的数据直接从内存中处理,通常会把服务器百分之75到80的物理内存分配给innodb的缓存池。

3、 使用每个表的相应主键设计数据库时 ,将自动优化涉及这些列的操作。引用WHERE 子句,ORDER BY子句, GROUP BY 子句和连接操作中的主键列非常快 。

4、 插入,更新和删除通过称为更改缓冲的自动机制进行优化InnoDB不仅允许对同一个表进行并发读写访问,还可以缓存已更改的数据以简化磁盘I / O.

5、 插入,更新和删除通过称为更改缓冲的自动机制进行优化InnoDB不仅允许对同一个表进行并发读写访问,还可以缓存已更改的数据以简化磁盘I / O.

6、 从表中反复访问相同的行时,称为 自适应哈希索引的功能会接管以使这些查找更快,就像它们来自哈希表一样。

7、 截断每个表 文件表 空间非常快,并且可以释放磁盘空间以供操作系统重用,而不是释放系统表空间中只能InnoDB重用的空间

8、 BLOB使用DYNAMIC行格式 ,表数据的存储布局对于长文本字段更有效

9、 您可以通过查询INFORMATION_SCHEMA 来监视存储引擎的内部工作方式 

10、 可以通过查询性能架构来监控存储引擎的性能详细信息 




五、优化

1、 增长的表增加了几十或几百兆字节,请考虑使用该OPTIMIZE TABLE语句重新组织表并压缩任何浪费的空间

2、 InnoDB,长PRIMARY KEY(具有冗长值的单个列,或形成长复合值的多个列)浪费了大量磁盘空间,要减少主key 还是普通key的长度,都能节约大量磁盘空间。

3、使用VARCHAR来代替可变长的char 并且限制列不能为空,可以很好地解决表空间优化的问题,

4、 对于较大的表或包含大量重复文本或数字数据的表,请考虑使用 COMPRESSED行格式。将数据放入缓冲池或执行全表扫描需要较少的磁盘I / O. 在做出永久性决策之前,请使用COMPRESSEDCOMPACT行格式相比较 来衡量您可以实现的压缩量 

5、 要优化InnoDB事务处理,请在事务功能的性能开销和服务器的工作负载之间找到理想的平衡。

6、 通过发出SET AUTOCOMMIT=0START TRANSACTION声明将几个相关的数据更改操作包装到单个事务中 ,然后 COMMIT在进行所有更改后进行声明。

7、InnoDB如果该事务对数据库进行了修改,则必须在每次事务提交时将日志刷新到磁盘。当每次更改后都提交时(与默认的自动提交设置一样),存储设备的I / O吞吐量会限制每秒潜在操作的数量。
      或者,对于仅包含单个SELECT语句的事务,启用此选项AUTOCOMMIT有助于 InnoDB识别只读事务并对其进行优化

8、 插入,更新或删除大量行后,避免执行回滚。为了避免,增服务器内存大小,     进行设置, innodb_change_buffering=all 以便除插入外还缓冲更新和删除操作。或者失控了,进程杀不掉,机器crash了,没办法只能关机重启。是因为我们无法取消正在回滚的事务。在极端情况下,回滚事务时,预计将需要一个非常长的时间,它可能会更快开始InnoDB innodb_force_recovery 的设置3或更大来避免。3的意思崩溃恢复后不执行事务回滚。


9、 innodb_flush_log_at_trx_commit 参数设置 为0. InnoDB尝试每秒刷新一次日志

10、 对于读密集型的应用(比如报表生成),可以通过把一系列查询语句放到start transaction read only和commit之间。或者
把autocommit配置打开。或者可以简单的通过不要在查询语句中间穿插dml语句来提高性能。

       事务以START TRANSACTION READ ONLY语句启动 在这种情况下,尝试更改数据库(for InnoDB MyISAM或其他类型的表)会导致错误,并且事务将继续处于只读状态、


11、 日志缓冲区的大小 大型日志缓冲区可以在事务提交之前运行大型 事务,而无需将日志写入磁盘因此,如果您有更新,插入或删除许多行的事务,则使日志缓冲区更大可以节省磁盘I / O. 使用 配置选项配置日志缓冲区大小 ,可以在MySQL 8.0中动态配置。 innodb_log_buffer_size


12、 innodb_log_write_ahead_size 配置选项以避免 read-on-write 此选项定义重做日志的预写块大小 。
       innodb_log_write_ahead_size 相对于操作系统或文件系统高速缓存块大小 设置该 值太低会导致读写。fsync由于一次写入多个块,因此将值设置得过高可能会对日志文件写入的性能产生轻微影响 

13、 优化用户线程等待刷新重做的旋转延迟的使用。 高并发期间,您可能希望避免在旋转延迟上消耗处理能力,以便可以将其用于其他工作。

        
  • innodb_log_wait_for_flush_spin_hwm:定义最大平均日志刷新时间,超过该时间,用户线程在等待刷新的重做时不再旋转。默认值为400微秒。
  • innodb_log_spin_cpu_abs_lwm:定义在等待刷新重做时用户线程不再旋转的最小CPU使用量。该值表示为CPU核心使用量的总和。例如,默认值80是单个CPU核心的80%。在具有多核处理器的系统上,值150表示100%使用一个CPU核心加50%使用第二个CPU核心。
  • innodb_log_spin_cpu_pct_hwm:定义在等待刷新的重做时用户线程不再旋转的最大CPU使用量。该值表示为所有CPU核心的总处理能力的百分比。默认值为50%。例如,两个CPU内核的100%使用率是具有四个CPU内核的服务器上组合CPU处理能力的50%。
     innodb_log_spin_cpu_pct_hwm 配置选项方面处理器的亲和性。例如,如果服务器有48个内核但 mysqld进程仅固定为4个CPU内核,则忽略其他44个CPU内核。


14、优化快速批量插入insert 语句。把执行的sql 用 SET autocommit=0; ... SQL import statements ... COMMIT;
        如果您UNIQUE对辅助密钥约束,则可以通过在导入会话期间临时关闭唯一性检查来加速表导入:
         SET unique_checks=0; ... SQL import statements ... SET unique_checks=1;
         如果FOREIGN KEY表中约束,则可以通过在导入会话期间关闭外键检查来加速表导入: SET foreign_key_checks=0; ... SQL import statements ... SET foreign_key_checks=1;
    
15、INSERT 如果需要插入许多行, 请使用多行语法来减少客户端和服务器之间的通信开销

 16、 在使用自动增量列进行批量插入时,设置 innodb_autoinc_lock_mode为2(交错)而不是1(连续)。   

17、 在某些版本的GNU / Linux和Unix中,使用Unix fsync()调用( InnoDB默认情况下使用)和类似方法将文件刷新到磁盘的速度非常慢。如果数据库写入性能存在问题,请使用innodb_flush_method 参数设置为on进行基准测试O_DSYNC

18、配置写缓冲区的阈值大小
默认情况下,在InnoDB创建新数据文件(如新日志文件或表空间文件)时,只有在完全写入文件后才会将写入缓冲区的内容刷新到磁盘,这可能导致发生大量磁盘写入活动立刻。要强制进行较小的定期刷新,请使用innodb_fsync_threshold (在MySQL 8.0.13中引入)为写缓冲区定义阈值大小(以字节为单位)。达到阈值大小时,写缓冲区的内容将刷新到磁盘。默认值0强制使用默认行为。


19、 控制InnoDB缓冲更改数据的数据更改操作类型 ,以避免频繁的小磁盘写入。 因为默认是缓冲所有类型的数据更改操作,所以只有在需要减少缓冲量时才更改此设置。

您可以InnoDB 使用innodb_change_buffering 配置参数控制执行更改缓冲 的范围您可以为插入,删除操作(当索引记录最初标记为删除时)和清除操作(物理删除索引记录时)启用或禁用缓冲。更新操作是插入和删除的组合。默认 innodb_change_buffering值为 all。 注意: 如果索引包含降序索引列或主键包含降序索引列,则不支持对辅助索引进行更改缓冲。


20、 InnoDB如果上下文切换是瓶颈,则 处理的并发线程数设置限制。 您可以通过设置配置参数来限制并发线程数 innodb_thread_concurrency一旦执行的线程数达到此限制,其他线程innodb_thread_sleep_delay在放入队列之前会休眠几十微秒(由配置参数 设置)。

21、 当系统具有未使用的I / O容量时,更多预读可以提高查询性能,对于负载较重的就不用调了。
22、配置后台io线程数: InnoDB使用后台 线程来为各种类型的I / O请求提供服务。您可以使用innodb_read_io_threads innodb_write_io_threads 配置参数配置在数据页上为读写I / O提供服务的后台线程 数。这些参数分别表示用于读取和写入请求的后台线程数。它们在所有支持的平台上都有效。您可以在MySQL选项文件(my.cnfmy.ini)中设置这些参数的值; 您无法动态更改值。这些参数的默认值是4,允许值的范围是1-64
这些配置选项的目的是InnoDB在高端系统上实现 更高的可扩展性。每个后台线程最多可处理256个待处理的I / O请求。后台I / O的主要来源是预读请求

23、 控制I / O InnoDB在后台执行的程度, 您观察到性能周期性下降,则可以缩减此设置。
InnoDB中 主线程是一个在后台执行各种任务的线程。这些任务中的大多数都与I / O相关,例如从缓冲池中刷新脏页或将更改从插入缓冲区写入适当的二级索引。
该参数innodb_io_capacity 表示InnoDB可用的总I / O容量。此参数应设置为大约系统每秒可执行的I / O操作数。该值取决于您的系统配置。 innodb_io_capacity设置,主线程估计可根据设定值后台任务的I / O带宽。

24、内部基准测试表明,该算法不仅可以保持吞吐量,还可以显着提高整体吞吐量。
由于自适应刷新会显着影响工作负载的I / O模式,因此 innodb_adaptive_flushing 配置参数可让您关闭此功能。innodb_adaptive_flushingis 的默认值 ON,启用自适应刷新算法。您可以在MySQL选项文件(my.cnfmy.ini)中设置此参数的值,或使用SET GLOBAL 命令动态更改它,该命令需要 SYSTEM_VARIABLES_ADMIN SUPER权限。
有关微调InnoDB 缓冲池刷新行为的信息,请参见第15.6.3.7节“微调InnoDB缓冲池刷新 
该算法适用于某些类型的工作负载,但不适用于其他工作负载,因此如果您观察到性能周期性下降,可能会关闭此设置

25、 利用多核处理器及其高速缓存配置,最大限度地减少上下文切换的延迟。 在所有处理器内核共享快速高速缓存的系统上,您可以通过设置减少最大延迟或完全禁用忙碌循环 innodb_spin_wait_delay=0。默认值是6、
    单位是微妙。

26、 确保频繁访问(  )页面保留在缓冲池中。
配置参数 innodb_old_blocks_pct控制LRU列表  的百分比的默认值 innodb_old_blocks_pct 37,对应于3/8原固定比率。值范围是5(缓冲池中的新页面很快就会老化)到95 (只有5%的缓冲池是为热页保留的,这使算法接近熟悉的LRU策略)。 配置参数 innodb_old_blocks_time 指定第一次访问页面之后的时间窗口(以毫秒为单位),在此期间可以访问该时间窗口而不移动到LRU列表的前端(最近使用的端点)。默认值 innodb_old_blocks_time 1000增加此值会使越来越多的块可能从缓冲池中更快地老化。

这两个innodb_old_blocks_pct innodb_old_blocks_time是动态的,全球性,可以在MySQL选项文件(指定my.cnfmy.ini)在与运行时或更改SET GLOBAL 命令。
在混合工作负载中,大多数活动是OLTP类型,并且定期批量报告查询会导致大量扫描,因此在innodb_old_blocks_time批处理运行期间设置值 可以帮助将正常工作负载的工作集保留在缓冲池中。
扫描不能完全适合缓冲池的大型表时,设置 innodb_old_blocks_pct为较小的值会使只读取一次的数据占用缓冲池的大部分。例如,设置innodb_old_blocks_pct=5将此数据限制为仅读取一次到缓冲池的5%。
扫描适合内存的小表时,在缓冲池中移动页面的开销较少,因此可以保留 innodb_old_blocks_pct默认值,甚至更高,例如innodb_old_blocks_pct=50
innodb_old_blocks_time 参数 的效果 比参数更难预测 innodb_old_blocks_pct ,相对较小,并且随工作量变化更大。要达到最佳值,如果调整后的性能提升innodb_old_blocks_pct不充分,请执行自己的基准测试 



27 、 InnoDB 日志文件通常保持较小,以避免崩溃后的长启动时间、 如果您将日志文件人为地缩小以避免长启动时间,则现在可以考虑增加日志文件大小以减少由于重做日志记录的回收而发生的I / O、
        
28、配置多个缓冲池实例, 对于具有数千兆字节范围的缓冲池的系统,将缓冲池划分为单独的实例可以通过减少不同线程读取和写入缓存页面时的争用来提高并发性。此功能通常用于缓冲池大小在千兆字节范围内的系统。使用innodb_buffer_pool_instances 配置选项配置多个缓冲池实例 ,您也可以调整该 innodb_buffer_pool_size值。
要启用多个缓冲池实例,请将innodb_buffer_pool_instances配置选项设置为 大于1(默认值)的值,最大为64(最大值)。仅当您设置innodb_buffer_pool_size为1GB或更大的大小时,此选项才会生效 您指定的总大小在所有缓冲池之间分配。为了获得最佳效率,指定的组合innodb_buffer_pool_instances innodb_buffer_pool_size,使得每个缓冲池实例是至少为1GB。


29、 增加最大并发事务数, 撤消日志是与单个事务关联的撤消日志记录的集合,  innodb_rollback_segments 配置选项定义回退段的数目。每个回滚段最多支持1023个并发数据修改事务。

30、 将清除操作(一种垃圾收集)移动到后台线程中。 要控制此功能,请增加配置选项的值innodb_purge_threads如果DML操作集中在单个表或几个表上,请将设置保持为低,以便线程不会相互竞争以访问繁忙表。如果DML操作分布在许多表中,请增加设置。它的最大值为32. innodb_purge_threads是非动态配置选项,这意味着它无法在运行时配置。配置,

31、 减少InnoDB并发线程之间的切换量 ,以便繁忙服务器上的SQL操作不会排队并形成 交通堵塞。 为该innodb_thread_concurrency 选项设置一个值, 对于高功率的现代系统,最多约为32。
增加innodb_concurrency_tickets 选项的值 ,通常为5000左右。这些选项组合设置了线程数量的上限 InnoDB 任何时候进程,并允许每个线程在被换出之前做大量的工作,这样等待线程的数量保持很低,操作可以在没有过多上下文切换的情况下完成。





参考:https://dev.mysql.com/doc/refman/8.0/en/
打赏
赞(0) 打赏
未经允许不得转载:同乐学堂 » 想要深度优化MySQL,一篇不得不看的文章.

特别的技术,给特别的你!

联系QQ:1071235258QQ群:710045715

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫打赏

微信扫一扫打赏

error: Sorry,暂时内容不可复制!