【MySQL篇】持久化和非持久化统计信息的深度剖析(第一篇,总共六篇)

news2024/11/28 1:20:59

💫《博主介绍》:✨又是一天没白过,我是奈斯,DBA一名✨

💫《擅长领域》:✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux,也在扩展大数据方向的知识面✌️

💖💖💖大佬们都喜欢静静的看文章,并且也会默默的点赞收藏加关注💖💖💖

    哈喽各位小伙伴,好久不见甚是想念。今天给大家上强度,讲解一下和SQL优化有关的内容——统计信息、优化器、执行计划、hint干预等。众所周知,优化器在SQL执行过程中扮演着至关重要的角色,它依赖于统计信息来为每个SQL语句制定最优的执行计划。而这些统计信息对于优化器的决策具有决定性的影响。因此,了解和掌握统计信息、优化器、执行计划、hint干预对于数据库的性能调优至关重要。接下来,我们将探讨统计信息、优化器、执行计划、hint干预的相关知识,帮助大家更好地理解并优化自己的数据库性能。

    因为统计信息、优化器、执行计划、hint干预涉及到的内容过多,为了使大家更好消化,我将分成六篇文章来进行介绍,以便大家因为篇幅过长而感到阅读疲惫。六篇的内容分别如下,让大家先做了解:

  • 第一篇:持久化和非持久化统计信息的深度剖析(当前篇)
  • 第二篇:全面理解优化器和SQL语句的解析步骤
  • 第三篇:SQL执行计划之访问路径
  • 第四篇:SQL执行计划之多表连接
  • 第五篇:精细化查询优化:如何有效使用Hint对优化器的执行计划进行干预
  • 第六篇:SQL性能优化实战案例

                        

目录

1.1 持久化统计信息(既innodb_stats_persistent=ON,默认on,生产必须持久化)

(1)相关参数

(2)配置每张表的统计信息参数

案例一:create表时配置表的持久化统计信息

(3)查看统计信息

(4)手动收集统计信息

4.1 analyze方式收集,oracle也支持(analyze是单表收集统计信息)

案例一:计算ANALYZE TABLE复杂性(消耗的读取)

4.2 mysqlcheck命令方式收集(mysqlcheck命令是全表全库收集统计信息)

(5)8.0版本直方图的最新变化

(6)解决统计信息差别较大的问题(执行计划受统计信息影响,统计信息不准会导致执行计划不准)

案例一:通过设置STATS_SAMPLE_PAGES或者设置innodb_stats_persistent_sample_pages解决统计信息不准问题

1.2 非持久化统计信息(既innodb_stats_persistent=OFF,默认on,不推荐使用仅了解)

(1)相关参数

(2)设置非持久化统计信息的两种方式


                 

    那让我们开始今天统计信息的介绍。

    首先MySQL统计信息是指数据库通过采样、统计出来的表、索引的相关信息,例如:表的记录数、聚集索引page个数、字段Cardinality....。MySQL在生成执行计划时,需要根据索引的统计信息进行估算,计算出 最低代价 (或者说是最小开销)的执行计划。需要注意哦,MySQL支持有限的索引统计信息,因存储引擎不同而统计信息收集的方式也不同。而且MySQL官方关于统计信息的概念介绍几乎等同于无(官方文档的链接在下面,有兴趣的小伙伴可以看看),不过对于已经接触过其它类型数据库的小伙伴而言(比如oracle),理解这个概念应该不在话下。在oracle中统计信息是非常丰富的,在以后的篇幅中我也会介绍,今天还是主要介绍MySQL的。相对于其它数据库,MySQL统计信息无法手工删除,并且MySQL 8.0之前的版本是没有直方图的。optimizer优化器根据统计信息对每个sql语句执行的执行计划(执行计划受统计信息影响)。

    MySQL统计信息的存储分为两种,非持久化和持久化统计信息。

               

官方文档对统计信息的介绍:

MySQL :: MySQL 8.0 Reference Manual :: 17.8.10 Configuring Optimizer Statistics for InnoDB

                

Oracle和MySQL统计信息的区别:

Oracle:统计信息是在特定的时间收集的全实例的,不是自动收集。当对象还没有统计信息时,那么先通过动态采样技术来选择执行计划,默认2级别的动态采样,采取对象的64个数据块进行分析。

MySQL:默认的持久化统计信息自动进行收集统计信息,但是需要注意MySQL InnoDB默认是以表为单位来收集和存储统计数据的。

          

1.1 持久化统计信息(既innodb_stats_persistent=ON,默认on,生产必须持久化)

    持久化统计信息在数据库重启统计信息不丢失,统计信息会被持久化到物理表中,会给出最优的执行计划,稳定和精确,对于大表也节省了收集统计信息的所需资源。5.6.6开始默认使用了持久化统计信息。

               

持久化统计信息在以下情况会被自动更新:

1)innodb_stats_auto_recalc为on,自动更新统计信息。阈值是表中行数的10%发生更改。

2)create table、create index、alter table、truncate table等涉及数据修改的DDL语句

3)手动更新统计信息,注意执行过程中会加读锁:analyze table tablename。

4)dict_stats_thread线程专门处理统计信息。

5)而如果变更的行数超过16+n_rows/16(6.25%)或者表修改的行超过1/6或者20亿条时

           

(1)相关参数

一、innodb_stats_persistent

参数含义是否启用持久化统计信息功能

默认值ON

作用:变量控制统计信息是否持久化,统计信息在早期的MySQL中是不持久化,在新版本的MySQL中持久化统计信息是默认的选项。当变量打开时,统计信息就会被持久化到物理表中,统计信息会更加的稳定和精确,对于大表也节省了收集统计信息的所需资源。如果为off,可能会频繁地重新计算统计信息,这可能会导致查询执行计划的变化。  

      

二、innodb_stats_auto_recalc

参数含义:是否自动触发更新统计信息

默认值:ON

触发阈值表变化的数据是否超过10%,超过自动收集统计信息。

作用:InnoDB会长期追踪每一张表的行数,判断更新的记录是否超过表记录总数的1/10,超过那么就把这张表加入到后台的recalc pool中。由于自动统计信息重新计算(发生在后台)是异步,在运行影响超过10%的表的DML操作时(即innodb_stats_auto_recalc启用后),可能不会立即重新计算统计信息。在某些情况下,统计重新计算可能会延迟几秒钟(10s)。如果在更改表的重要部分之后立即需要最新统计信息,请运行ANALYZE TABLE以启动统计信息的同步(前台)重新计算。

    如果禁用了innodb_stats_auto_recalc,请在对索引列进行实质性更改后,通过为每个适用的表发出ANALYZE TABLE语句来确保统计信息的准确性。

    此设置适用于启用innodb_stats_persistent选项时创建的表。也可以在CREATE TABLE或者ALTER TABLE时通过STATS_AUTO_RECALC语法来指定比率。

        

三、innodb_stats_persistent_sample_pages

参数含义持久化统计信息采样的索引页数。分析配置的页数,优化器根据统计信息给出执行计划

默认值20

作用:在估计索引列的基数和其他统计信息(例如由ANALYZE TABLE计算的统计信息)时要采样的索引页数。增加该值可以提高索引统计的准确性,从而改进查询执行计划,但代价是在InnoDB表执行ANALYZE TABLE时增加I/O。

     该值设置的越大,统计出的n_rows值越精确,但是统计耗时也就最久

     该值设置的越小,统计出的n_rows值越不精确,但是统计耗时特别少。

1)统计信息不够准确,优化器选择次优计划:如果确定统计信息不够准确,则应增加innodb_stats_persistent_sample_pages的值,直到统计估计值足够准确。但是过多地增加innodb_stats_persistent_sample_pages可能会导致ANALYZE TABLE运行缓慢。

2)ANALYZE TABLE太慢:在这种情况下,应减少innodb_stats_persistent_sample_pages,直到ANALYZE TABLE执行时间可以接受。但是过多地降低该值可能会导致生成不准确的统计信息和执行计划的问题。

          

四、innodb_stats_include_delete_marked

默认值:OFF

作用:在5.7.16中引入的此参数,默认为不启用,表示在未提交的事务有从表中删除行,则InnoDB在收集统计信息时,将会排除这些delete_marked行。这可能会导致除READ UNCOMMITTED之外的事务隔离级别的事务,运行的不是最佳的执行计划。

为了避免这种情况,可以启用innodb_stats_include_delete_marked以确保在计算持久化统计信息时InnoDB包含Delete-marked记录。

          

(2)配置每张表的统计信息参数

    innodb_stats_persistent、innodb_stats_auto_recalc和innodb_stats_persistent_sample_pages是全局配置选项。若要覆盖这些系统范围的设置并为各个表配置统计信息参数,可以在CREATE TABLE或ALTER TABLE语句中定义STATS_PERSISTENT、STATS_AUTO_RECALC和STATS_SAMPLE_PAGES子句。

一、STATS_PERSISTENT

含义:指定是否为InnoDB表启用持久统计信息。

设置值:

DEFAULT:表示表的持久统计信息设置由innodb_stats_persistent配置选项确定

1:表示启用表的持久统计信息

0:关闭此功能

          

二、STATS_AUTO_RECALC

含义:指定是否自动触发InnoDB表的持久统计信息。

设置值:

DEFAULT:表示表的持久统计信息设置由innodb_stats_auto_recalc配置选项确定

1:表示表中10%的数据发生更改时将重新计算统计信息

0:禁用自动重新计算此表

          

 三、STATS_SAMPLE_PAGES

含义:指定在估计索引列的基数和其他统计信息(例如由ANALYZE TABLE计算的统计信息)时要采样的索引页数。

设置值:

DEFAULT:表示持久化统计信息采样的页数由innodb_stats_persistent_sample_pages配置选项确定 

案例一:create表时配置表的持久化统计信息

CREATE TABLE't1`(
`id` int(8) NOT NULL auto increment, 
data` varchar(255), 
date` datetime,
PRIMARY KEY (`id`),
INDEX'DATE IX` (`date`)
) ENGINE=InnoDB,
STATS PERSISTENT=1,
STATS AUTO RECALC=1, 
STATS SAMPLE PAGES=25;

              

(3)查看统计信息

table statistics相关视图:

mysql> select * from mysql.innodb_table_stats where table_name='表名';

database_name:数据库名

table_name:表名

last_update:统计信息最后一次更新时间,sql执行计划受统计信息影响。

n_rows:表的行数

clustered_index_size:聚集索引的页的数量

sum_of_other_index_sizes:其他索引的页的数量

mysql> select * from information_schema.tables where table_name='表名';

mysql> select * from information_schema.statistics where table_name='表名';

注意:mysql.innodb_table_stats会在持久化统计信息下自动更新,而information_schema.tables和information_schema.statistics不会自动更新需要手动执行analyze table或者mysqlcheck命令方式收集,所以统计信息以按照mysql.innodb_table_stats表的信息为准。

index statistics相关视图:

mysql> select * from mysql.innodb_index_stats where table_name='表名';    ---会在持久化统计信息下自动更新

database_name:数据库名

table_name:表名

index_name:索引名

last_update:统计信息最后一次更新时间,sql执行计划受统计信息影响。

stat_name:统计信息名

stat_value:统计信息的值

sample_size:采样大小

stat_description:类型说明

          

(4)手动收集统计信息

4.1 analyze方式收集,oracle也支持(analyze是单表收集统计信息)

    innodb和myisam存储引擎都可以通过执行analyze table tablename来收集表和索引的统计信息。除非执行计划不准确,否则不要轻易执行该操作,如果是很大的表该操作会影响表的性能(单表9亿行的收集秒级完成,即使整个实例有2T,并且上千张表,通过mysqlcheck工具进行所有库的收集,也是几分钟就完成,亲测)

    由于Analyze table会更新数据字典里的统计信息表(8.0)因此在innodb_read_only 开关被打开时有可能会导致执行失败。在analyze table的过程中会持有InnoDB表的read only锁,因此会存在短暂的阻塞用户写入更新删除的操作。除此之外analyze table要把table从table definition cache刷出来,因此还会需要一个flush lock,此时如果有长事务使用了这张表,那么必须等待长事务结束。

注意:ANALYZE、CHECK、OPTIMIZE、ALTER TABLE执行期间将对表进行锁定,因此一定注意要在数据库不繁忙的时候执行相关的操作。

5.7语法:

ANALYZE [NO_WRITE_TO_BINLOG | LOCAL]
TABLE tbl_name [, tbl_name] ...

              

8.0语法(8.0中支持了直方图统计信息,因此analyze table还扩充了Histogram语法):

ANALYZE [NO_WRITE_TO_BINLOG | LOCAL]
TABLE tbl_name [, tbl_name] ...

ANALYZE [NO_WRITE_TO_BINLOG | LOCAL]
    TABLE tbl_name
    UPDATE HISTOGRAM ON col_name [, col_name] ...
        [WITH N BUCKETS]

ANALYZE [NO_WRITE_TO_BINLOG | LOCAL]
    TABLE tbl_name
    DROP HISTOGRAM ON col_name [, col_name] ...

          

InnoDB表的ANALYZE TABLE复杂性(消耗的读取):

1)采样的页数,由innodb_stats_persistent_sample_pages定义。

2)表中索引列的数量(由多个数相加而成,参考下面案例)。

3)分区数量。如果表没有分区,则分区数被视为1。

总结:ANALYZE TABLE复杂性度=innodb_stats_persistent_sample_pages * 表中索引列的数量(多个数相加而成) * 分区数 * innodb_page_size

    通常结果值越大,ANALYZE InnoDB TABLE的执行时间越长。

    innodb_stats_persistent_sample_pages定义在全局级别采样的页数。要设置单个表的采样页数,请使用带有CREATE TABLE或ALTER TABLE的STATS_SAMPLE_PAGES选项。

    如果innodb_stats_persistent = OFF,则采样的页数由innodb_stats_transient_sample_pages定义。

                 

案例一:计算ANALYZE TABLE复杂性(消耗的读取)

ANALYZE TABLE复杂性度=innodb_stats_persistent_sample_pages * 表中索引列的数量(多个数相加而成) * 分区数 * innodb_page_size
O(n_sample
  * (n_cols_in_uniq_i
     + n_cols_in_non_uniq_i
     + n_cols_in_pk * (1 + n_non_uniq_i))
  * n_part * innodb_page_size)

n_sample:是取样的页数(定义为innodb_stats_persistent_sample_pages)

n_cols_in_uniq_i:所有唯一索引中所有列的总数(不包括主键列)

n_cols_in_non_uniq_i:所有非唯一索引中所有列的总数

n_cols_in_pk:主键中的列数(如果没有定义主键,InnoDB在内部创建单列主键)

n_non_uniq_i:表中非唯一索引的数目

n_part:是分区的数量。如果没有定义分区,则该表被视为单个分区。

innodb_page_sizeinnodb每个页的大小是16K,且不可更改

SQL> CREATE TABLE t (
  a INT,
  b INT,
  c INT,
  d INT,
  e INT,
  f INT,
  g INT,
  h INT,
  PRIMARY KEY (a, b),
  UNIQUE KEY i1uniq (c, d),
  KEY i2nonuniq (e, f),
  KEY i3nonuniq (g, h)
);

SQL> SELECT index_name, stat_name, stat_description
       FROM mysql.innodb_index_stats WHERE
       database_name='test' AND
       table_name='t' AND
       stat_name like 'n_diff_pfx%';

n_cols_in_uniq_i:所有唯一索引中不包括主键列的所有列的总数为2(c和d)
n_cols_in_non_uniq_i:所有非唯一索引中所有列的总数,为4(e,f,g和h)
n_cols_in_pk:主键中的列数为2(a和b)
n_non_uniq_i:表中非唯一索引的数量是2(i2nonuniq和i3nonuniq))
n_part:分区数,是1。

那么读取t表:

innodb_stats_persistent_sample_pages=20

n_cols_in_uniq_i =2

n_cols_in_non_uniq_i=4

n_cols_in_pk=2

n_non_uniq_i=2

n_part=1

innodb_page_size=16kb

估计表t读取20*(2+4+2*(1+2))*1*16kb=3840kb,为3.75M

                

4.2 mysqlcheck命令方式收集(mysqlcheck命令是全表全库收集统计信息)

    mysqlcheck是用来检查、修复、优化、分析表。只有在数据库运行的状态下才可运行,意味着不用停止服务操作。

    mysqlcheck其实就是CHECK TABLE(检查表), REPAIR TABLE(修复表), ANALYZE TABLE(分析表)以及OPTIMIZE TABLE(优化表)的便捷操作集合,利用指定参数将对于的SQL语句发送到数据库中进行执行。同样对于那些存储引擎的的支持,也受对于表维护SQL语句的限制(如check 则不支持MEMORY表, repair 则不支持 InnoDB表)

注意:ANALYZE、CHECK、OPTIMIZE、ALTER TABLE执行期间将对表进行锁定,因此一定注意要在数据库不繁忙的时候执行相关的操作。

             

mysqlcheck参数:

参数选项描述
-A, --all-databases选择所有的库
-B, --databases选择多个库
-a, --analyze分析表ANALYZE TABLE
-c, --check 检查表CHECK TABLE
-C, --check-only-changed最后一次检查之后变动的表CHECK TABLE
-m, --medium-check近似完全检查,速度比--extended稍快CHECK TABLE
-o, --optimize优化表OPTIMIZE TABLE
--auto-repair自动修复表
-g, --check-upgrade检查表是否有版本变更,可用 auto-repair修复
-F, --fast只检查没有正常关闭的表
-f, --force忽悠错误,强制执行
-e, --extended表的百分百完全检查,速度缓慢
-q, --quick最快的检查方式,在repair 时使用该选项,则只会修复 index tree
-r, --repair修复表REPAIR TABLE
-s, --silent 只打印错误信息
-V, --version显示版本

                            

收集库所有表的统计信息:

收集test库:

[root@mgr1 ~]# mysqlcheck -uroot -p123456 -S /mysql/data/3306/mysql.sock --analyze --databases test

                       

收集所有库:

[root@mgr1 ~]# mysqlcheck -uroot -p123456 -S /mysql/data/3306/mysql.sock --analyze --all-databases

SQL> select * from mysql.innodb_table_stats where database_name='test';     ---test库所有表的统计信息更新为最新

                 

(5)8.0版本直方图的最新变化

    MySQL 5.7并没有提供直方图的功能,某些情况下(如数据分布不均)仅仅更新统计信息不一定能得到准确的执行计划,只能通过index hint的方式指定索引。

    在MySQL 8.0中支持了直方图统计信息,因此analyze table还扩充了Histogram语法,参考官方文档即可。

    直方图是MySQL 8.0中新增的统计信息方式,Analyze table加上直方图语句就可以操作直方图的信息, 直方图并不是存储引擎层实现的,而是在Server层利用InnoDB存储引擎实现的系统表mysql.column_stats,MySQL利用JSON类型的字段来保存直方图的信息,其实现的核心代码在sql/histogram目录下。

    直方图的具体的操作包括:更新直方图以及drop直方图,其中更新直方图还可以重新指定bucket的数目,需要注意的是直方图不支持加密表,不支持GIS列以及JSON列,以及不支持单列唯一索引的列。

    通过histogram_generation_max_mem_size参数可以调整用于生成直方图的采样记录内存大小,通过查看information_schema的column_statistic表可以查看sampling-rate。

    最新的MySQL8.0.19中,InnoDB实现了自己的采样算法,来避免全表扫描。在MySQL计算直方图填充时会调用Handler层的ha_sample_init, ha_sample_next以及ha_sample_end接口。在8.0.19前InnoDB并没有实现sample的接口,而是用的Handler层的默认实现rnd_next,也就是全表扫描,直到独到采样比率的数据为止。这里有一个问题,如果采样率设置为10%,那采样只是读前10%的记录。更科学的做法是在整棵索引树上均匀的采样。在新版本中终于有了InnoDB引擎层的sample实现。目前的代码只支持单线程的采样,但是从代码架构看已经实现了parallel_reader的接口,不久后一定会实现多线程并行的采样。InnoDB的采样是交给了单独的worker线程来实现的,一般是对主键进行。整体思路就是根据采样比率相对平均的选择叶子节点页面,假设采样率是10%,那么会选择一个叶子页面后跳过9个叶子页面,被选中的页面中会对所有的记录进行采样。

          

(6)解决统计信息差别较大的问题(执行计划受统计信息影响,统计信息不准会导致执行计划不准)

    如果自动更新持久化统计信息后发现与实际count(*)数据量差距较大,可考虑增加表采样的数据页,两种方式修改:

修改一:全局变量(影响所有表)

innodb_stats_persistent_sample_pages默认20个页面。持久化统计信息采样的页数。分析配置的页数,优化器根据统计信息给出执行计划

缺点:过多地增加innodb_stats_persistent_sample_pages可能会导致ANALYZE TABLE运行缓慢。

           该值设置的越大,统计出的n_rows值越精确,但是统计耗时也就最久

           该值设置的越小,统计出的n_rows值越不精确,但是统计耗时特别少。

         

修改二:CREATE/ALTER表的参数(只影响设置的表)  

ALTER TABLE TABLE_NAME STATS_SAMPLE_PAGES=40;    ---经测试,此处STATS_SAMPLE_PAGES的最大值是65535,超出会报错。

STATS_SAMPLE_PAGES:指定在估计索引列的基数和其他统计信息(例如由ANALYZE TABLE计算的统计信息)时要采样的索引页数表示持久化统计信息采样的页数innodb_stats_persistent_sample_pages配置选项确定。

          

案例一:通过设置STATS_SAMPLE_PAGES或者设置innodb_stats_persistent_sample_pages解决统计信息不准问题

1)创建表

SQL> create table tb_700w like tb;
SQL> insert into tb_700w select * from tb limit 7000000;

SQL> select * from mysql.innodb_table_stats where table_name='tb_700w';
---tb_700w真实有700万行数据,由于innodb_stats_persistent_sample_pages进行自动持久化统计信息采样只采集20页,那么就会有误差

2)设置STATS_SAMPLE_PAGES:

SQL> ALTER TABLE tb_700w STATS_SAMPLE_PAGES=65535;    ---此处STATS_SAMPLE_PAGES的最大值是65535,超出会报错。
SQL> analyze table tb_700w;

SQL> select * from mysql.innodb_table_stats where table_name='tb_700w';    
---收集单表的STATS_SAMPLE_PAGES的最大值是65535个页,超出会报错。65535页还是不能给出准确的行数

3)设置innodb_stats_persistent_sample_pages:

注意:ANALYZE TABLE复杂性度=innodb_stats_persistent_sample_pages * 表中索引列的数量(多个数相加而成) * 分区数 * innodb_page_size,那么过多地增加innodb_stats_persistent_sample_pages,ANALYZE InnoDB TABLE的执行时间越长。

SQL> ALTER TABLE tb_700w STATS_SAMPLE_PAGES=default;                 ---恢复默认STATS_SAMPLE_PAGES,由innodb_stats_persistent_sample_pages配置选项确定
SQL> show variables like 'innodb_stats_persistent_sample_pages';     ---默认采集20页

算出innodb_stats_persistent_sample_pages最合适的值。公式:innodb_stats_persistent_sample_pages=ANALYZE TABLE复杂性度(大小)/表中索引列的数量(多个数相加而成)/分区数/innodb_page_size

SQL> show create table tb_700w\G;

SQL> SELECT index_name, stat_name, stat_description
       FROM mysql.innodb_index_stats WHERE
       database_name='test' AND
       table_name='tb_700w' AND
       stat_name like 'n_diff_pfx%';

详细算法参考上面(4)手动收集统计信息的案例一:计算ANALYZE TABLE复杂性(消耗的读取)

n_cols_in_uniq_i:所有唯一索引中不包括主键列的所有列的总数为0

n_cols_in_non_uniq_i:所有非唯一索引中所有列的总数,为0

n_cols_in_pk:主键中的列数为1(id)

n_non_uniq_i:表中非唯一索引的数量是0

n_part:分区数,是1。

那么读取tb_700w表:

n_cols_in_uniq_i =0

n_cols_in_non_uniq_i=0

n_cols_in_pk=1

n_non_uniq_i=0

n_part=1

innodb_page_size=16kb

innodb_stats_persistent_sample_pages=(1611Mx1024)/(0+0+1*(1+0))/1/16kb=103104

SQL> set global innodb_stats_persistent_sample_pages=103104; 
SQL> analyze table tb_700w;

SQL> select * from mysql.innodb_table_stats where table_name='tb_700w'; 
                       给出了最准确的统计信息

            

                    

1.2 非持久化统计信息(既innodb_stats_persistent=OFF,默认on,不推荐使用仅了解)

    非持久化统计信息存储在内存里,如果数据库重启统计信息将丢失,在下一次访问表时重新计算。会导致频繁地重新计算统计信息,这可能会导致查询执行计划的变化。不推荐使用也不是默认值。

    当innodb_stats_persistent = OFF或使用STATS_PERSISTENT = 0创建或更改单张表时,统计信息不会保留到磁盘。相反统计信息存储在内存中,并在服务器关闭时丢失。某些业务和某些条件下也会定期更新统计数据。

           

非持久化统计信息在以下情况会被自动更新(前提innodb_stats_on_metadata设置为on,默认off):

1)手动更新统计信息,注意执行过程中会加读锁:analyze table tablename

2)设置innodb_stats_on_metadata=ON(默认off),执行SHOW TABLE STATUS , SHOW INDEX,查询INFORMATION_SCHEMA下的TABLES, STATISTICS

3)启用--auto-rehash选项,这是默认设置。--auto-rehash选项会打开所有InnoDB表,打开表的操作会导致统计数据重新计算。使用mysql client登录。

4)表第一次被打开

5)距上一次更新统计信息,表1/16的数据被修改

总结:非持久化统计信息的缺点显而易见,数据库重启后如果大量表开始更新统计信息,会对实例造成很大影响,所以目前都会使用持久化统计信息。

             

(1)相关参数

一、innodb_stats_on_metadata

参数含义:表示是否InnoDB在(如SHOW TABLE STATUS)或访问INFORMATION_SCHEMA.TABLES或INFORMATION_SCHEMA.STATISTICS)操作期间更新统计信息。

默认值:OFF

作用:保留禁用的设置可以提高具有大量表或索引的模式的访问速度。它还可以提高涉及InnoDB表的查询的执行计划的稳定性。

此选项仅在优化器统计信息配置为非持久性时适用。当innodb_stats_persistent为off(默认on,启用持久化统计信息)时生效。或者使用STATS_PERSISTENT=0创建或修改单个表时,优化器统计信息不会被持久化到磁盘。在关闭持久化统计信息时,是否在show table status/查看information_schema的TABLES,STATISTICS表时更新统计信息(亲测关闭innodb_stats_persistent=off,在设置innodb_stats_on_metadata为on或者off下都使用show table status/查看information_schema的TABLES、STATISTICS表也不会更新统计信息,了解即可,生产环境必须开启持久化统计信息也是默认选项)

         

二、innodb_stats_transient_sample_pages

参数含义:表示每次随机采样页的数量

默认值8

作用:当innodb_stats_persistent = 0时,innodb_stats_transient_sample_pages的值会影响所有InnoDB表和索引的索引采样。更改索引样本大小时,请注意以下潜在的重大影响:

像1或2这样的小值可能导致基数估计不准确。

增加innodb_stats_transient_sample_pages值可能需要更多磁盘读取。远大于8(例如100)的值可能导致打开表或执行SHOW TABLE STATUS所花费的时间显着减慢。优化器可能会根据索引选择性的不同估计选择非常不同的查询计划。

               

(2)设置非持久化统计信息的两种方式

1)全局变量(影响所有表)

innodb_stats_persistent=OFF     ---默认on,启用持久化统计信息。变量控制统计信息是否持久化统计信息在早期的MySQL中是不持久化在新版本的MySQL中持久化统计信息是默认的选项当变量打开时,统计信息就会被持久化到物理表中统计信息会更加的稳定和精确,对于大表也节省了收集统计信息的所需资源。如果为off,可能会频繁地重新计算统计信息,这可能会导致查询执行计划的变化

        

2)CREATE/ALTER表的参数(只影响设置的表)

STATS_PERSISTENT=0    ---是否启用InnoDB表的持久统计功能。 默认值由innodb_stats_persistent配置选项决定。 值1启用表的持久统计,而值0关闭此特性。 在通过CREATE TABLE或ALTER TABLE语句启用持久统计信息后,在将代表性数据加载到表中之后,发出ANALYZE TABLE语句来计算统计信息。

STATS_PERSISTENT:指定是否为InnoDB表启用持久统计信息。默认值由innodb_stats_persistent配置选项确定。1:表示启用表的持久统计信息; 0:关闭此功能

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2248734.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

三开关VUE组件

一、使用效果 <template><QqThreeSwitch v-model"value" /><!-- <SqThreeSwitch v-model"value" :options"[test1, test2, test3]"><template #left-action><div style"display: flex"><IconMoon…

线段树与树状数组 (C++)

线段树&#xff1a;基于分治思想的二叉树&#xff0c;用于维护区间信息&#xff08;区间和&#xff0c;区间最值等&#xff09;&#xff0c;区间修改和区间查询的时间复杂度为logn 叶子节点存储元素本身&#xff0c;非叶子节点存取区间信息 1.节点&#xff1a;是一个结构体&a…

vue3 uniapp 扫普通链接或二维码打开小程序并获取携带参数

vue3 uniapp 扫普通链接或二维码打开小程序并获取携带参数 微信公众平台添加配置 微信公众平台 > 开发管理 > 开发设置 > 扫普通链接二维码打开小程序 配置链接规则需要下载校验文档给后端存入服务器中&#xff0c;保存配置的时候会校验一次&#xff0c;确定当前的配…

数据结构(初阶6)---二叉树(遍历——递归的艺术)(详解)

二叉树的遍历与练习 一.二叉树的基本遍历形式1.前序遍历(深度优先遍历)2.中序遍历(深度优先遍历)3.后序遍历(深度优先遍历)4.层序遍历&#xff01;&#xff01;(广度优先遍历) 二.二叉树的leetcode小练习1.判断平衡二叉树1&#xff09;正常解法2&#xff09;优化解法 2.对称二叉…

spring boot2.7集成OpenFeign 3.1.7

1.Feign Feign是一个声明式web服务客户端。它使编写web服务客户端更容易。要使用Feign&#xff0c;请创建一个接口并对其进行注释。它具有可插入注释支持&#xff0c;包括Feign注释和JAX-RS注释。Feign还支持可插拔编码器和解码器。Spring Cloud增加了对Spring MVC注释的支持&…

基于Redis内核的热key统计实现方案|得物技术

一、Redis热key介绍 Redis热key问题是指单位时间内&#xff0c;某个特定key的访问量特别高&#xff0c;占用大量的CPU资源&#xff0c;影响其他请求并导致整体性能降低。而且&#xff0c;如果访问热key的命令是时间复杂度较高的命令&#xff0c;会使得CPU消耗变得更加严重&…

CTF-Hub SQL 报错注入(纯手动注入)

​ 当输入1时&#xff0c;发现只有查询正确&#xff0c;基本上可以判断出没有回显 开始注入(工具hackerBar) 题目是报错注入&#xff0c;方向就比较明显&#xff0c;大致说一下用到的函数和原理。 常见报错注入函数&#xff1a; 通过 floor() 报错注入通过 extractValue() …

Elasticsearch中的节点(比如共20个),其中的10个选了一个master,另外10个选了另一个master,怎么办?

大家好&#xff0c;我是锋哥。今天分享关于【Elasticsearch中的节点&#xff08;比如共20个&#xff09;&#xff0c;其中的10个选了一个master&#xff0c;另外10个选了另一个master&#xff0c;怎么办&#xff1f;】面试题。希望对大家有帮助&#xff1b; Elasticsearch中的节…

linux安装mysql8.0.40

一、下载MySQL安装包 1.查看glibc版本 rpm -qa | grep glibc 2.到mysql官网下载安装包 ​ 二、解压安装 1.上传压缩包纸/usr/local 目录下&#xff0c;解压&#xff1a; tar -xvf mysql-8.0.40-linux-glibc2.17-x86_64.tar.xz 2.重命名&#xff1a; mv mysql-8.0.40-linux-…

【大数据学习 | Spark-Core】RDD的五大特性(包含宽窄依赖)

分析一下rdd的特性和执行流程 A list of partitions 存在一系列的分区列表A function for computing each split 每个rdd上面都存在compute方法进行计算A list of dependencies on other RDDs 每个rdd上面都存在一系列的依赖关系Optionally, a Partitioner for key-value RDDs…

在 Taro 中实现系统主题适配:亮/暗模式

目录 背景实现方案方案一&#xff1a;CSS 变量 prefers-color-scheme 媒体查询什么是 prefers-color-scheme&#xff1f;代码示例 方案二&#xff1a;通过 JavaScript 监听系统主题切换 背景 用Taro开发的微信小程序&#xff0c;需求是页面的UI主题想要跟随手机系统的主题适配…

【C语言】int *p[ ] 与 int (*p)[ ] 的区分辨析

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C语言 文章目录 &#x1f4af;前言&#x1f4af;基本概念&#xff1a;数组与指针&#x1f4af;理解 int *p[10] 与 int (*p)[10]1. int *p[10]&#xff1a;存放指针的数组2. int (*p)[10]&#xff1a;指向数组的指针 …

Vue3 el-table 默认选中 传入的数组

一、效果&#xff1a; 二、官网是VUE2 现更改为Vue3写法 <template><el-table:data"tableData"border striperow-key"id"ref"tableRef":cell-style"{ text-align: center }":header-cell-style"{background: #b7babd…

MT6769/MTK6769核心板规格参数_联发科安卓主板开发板方案

MT6769安卓核心板具有集成的蓝牙、FM、WLAN和GPS模块&#xff0c;是一个高度集成的基带平台&#xff0c;结合了调制解调器和应用处理子系统&#xff0c;以支持LTE/LTE-A和C2K智能手机应用。 该芯片集成了两个工作频率高达2.0GHz的ARMCortex-A75内核、六个工作频率高达1.70GHz的…

在Excel中处理不规范的日期格式数据并判断格式是否正确

有一个Excel表&#xff0c;录入的日期格式很混乱&#xff0c;有些看着差不多&#xff0c;但实际多一个空格少一个字符很难发现&#xff0c;希望的理想格式是 1980-01-01&#xff0c;10位&#xff0c;即&#xff1a;“YYYY-mm-dd”&#xff0c;实际上数据表中这样的格式都有 19…

flask请求头回显的学习和探究如何进行错误页面污染回显

请求头 首先我们要了解一些flask的请求和响应是利用了什么。 flask的请求和响应主要利用了werkzeug&#xff0c;那么我们就要先了解一下什么是werkzeug&#xff0c;其结构又是什么。 werkzeug是一个基于python开发的一个web工具包&#xff0c;其是flask的核心组件之一。其功能…

【Unity踩坑】Unity中父对象是非均匀缩放时出现倾斜或剪切现象

The game object is deformed when the parent object is in non-uniform scaling. 先来看一下现象 有两个Cube, Cube1&#xff08;Scale2,1,1)&#xff0c;Cube2&#xff08;Scale1,1,1&#xff09; 将Cube2拖拽为Cube2的子对象。并且将position设置为&#xff08;-0.6,1,0&a…

uni-app 蓝牙开发

一. 前言 Uni-App 是一个使用 Vue.js 开发&#xff08;所有&#xff09;前端应用的框架&#xff0c;能够编译到 iOS、Android、快应用以及各种小程序等多个平台。因此&#xff0c;如果你需要快速开发一款跨平台的应用&#xff0c;比如在 H5、小程序、iOS、Android 等多个平台上…

解决SSL VPN客户端一直提示无法连接服务器的问题

近期服务器更新VPN后&#xff0c;我的win10电脑一致无法连接到VPN服务器&#xff0c; SSL VPN客户端总是提示无法连接到服务端。网上百度尝试了各种方法后&#xff0c;终于通过以下设置方式解决了问题&#xff1a; 1、首先&#xff0c;在控制面板中打开“网络和共享中心”窗口&…

spring boot框架漏洞复现

spring - java开源框架有五种 Spring MVC、SpringBoot、SpringFramework、SpringSecurity、SpringCloud spring boot版本 版本1: 直接就在根下 / 版本2:根下的必须目录 /actuator/ 端口:9093 spring boot搭建 1:直接下载源码打包 2:运行编译好的jar包:actuator-testb…