MySQL如何进行索引重建操作?

在MySQL数据库中,没有类似于SQL Server数据库或Oracle数据库中索引重建的语法(ALTER INDEX ... REBUILD),那么在MySQL数据库中,是否有什么方式重建索引呢? 在官方文档中"2.11.10 Rebuilding or Repairing Tables or Indexes"中,提到下面三种方式可以Rebuild Index

·         Dump and Reload Method

·         ALTER TABLE Method

·         REPAIR TABLE Method

另外, OPTIMIZE TABLE也会对索引进行重建,下面我们来简单验证、测试一下,如有不对或不足的地方,敬请指正。

第一种方法(mysqldump导出然后重新导入),相当于重新CREATE INDEXES , 这里就不讨论了。下面我们来看看其它几种方法,那么要判断索引是否REBUILD了呢?我们来测试验证一下吧,新建测试表如下:

CREATE TABLE t1 (
    c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,

    c2 VARCHAR(100),

    c3 VARCHAR(100) )

ENGINE=InnoDB;

 

create index ix_t1_c2 on t1(c2);

DROP INDEX + CREATE INDEX方法

 

这种方法过于简单,这里不叙说了。其实也没有啥好说的。

ALTER TABLE方法

 

那么我们能否在MySQL中找到索引的创建或修改时间呢?经过查证,目前而言,MySQL中是没有相关系统表或视图会记录索引的创建时间的,我们可以用间接的方法来间接验证,有些方法不是特别可靠和准确,最准确的方法应该是阅读源码:

1:表的创建时间,可以间接推断索引的创建时间。因为索引的创建时间肯定在表的创建时间之后。

2:对应表的idb文件的修改或创建时间(若文件从创建后不曾修改过则可认为创建时间=修改时间,关于更多详细内容,参考“Linux如何查找文件的创建时间”),当然这种方法不是非常准确。我们知道,对于InnoDB存储引擎的表而言,对应的索引数据存储在ibd文件中,所以文件的创建时间或修改时间是间接判断索引创建时间。如果存储引擎为MyISAM的话,还有专门的索引文件MYI。

注意:show indexes from tablename不会显示索引创建时间

mysql> SELECT table_name,create_time FROM  information_schema.TABLES WHERE table_name=‘t1‘;
+------------+---------------------+

| TABLE_NAME | CREATE_TIME         |

+------------+---------------------+

| t1         | 2019-10-20 08:18:33 |

+------------+---------------------+

1 row in set (0.01 sec)

然后我们对表进行ALTER TABLE t1 ENGINE = InnoDB;进行操作后,然后去验证表的创建时间,如下所示,其实ALTER TABLE xxx ENGINE=InnoDB 其实等价于REBUILD表(REBUILD表就是重建表的意思),所以索引也等价于重新创建了。

在另外一个窗口,我们对比t1.ibd的创建时间,如下所示,也间接验证了表和索引都REBUILD了。(这里是MySQL 8.0.18 ,如果是之前的版本,还有frm之类的文件。)

 
[[email protected]-server MyDB]# ls -lrt t1*

-rw-r-----. 1 mysql mysql 131072 Oct 20 08:18 t1.ibd

[[email protected] MyDB]# stat t1.ibd

  File: ‘t1.ibd’

  Size: 131072          Blocks: 224        IO Block: 4096   regular file

Device: fd00h/64768d    Inode: 106665154   Links: 1

Access: (0640/-rw-r-----)  Uid: ( 1000/   mysql)   Gid: ( 1000/   mysql)

Context: system_u:object_r:mysqld_db_t:s0

Access: 2019-10-20 08:18:25.911990445 +0800

Modify: 2019-10-20 08:18:33.626989940 +0800

Change: 2019-10-20 08:18:33.626989940 +0800

 Birth: -

[[email protected] MyDB]# stat t1.ibd

  File: ‘t1.ibd’

  Size: 131072          Blocks: 224        IO Block: 4096   regular file

Device: fd00h/64768d    Inode: 106665156   Links: 1

Access: (0640/-rw-r-----)  Uid: ( 1000/   mysql)   Gid: ( 1000/   mysql)

Context: system_u:object_r:mysqld_db_t:s0

Access: 2019-10-20 08:20:50.866980953 +0800

Modify: 2019-10-20 08:20:51.744980896 +0800

Change: 2019-10-20 08:20:51.744980896 +0800

 Birth: -

 

REPAIR TABLE方法

 

REPAIR TABLE方法用于修复被破坏的表,而且它仅仅能用于MyISAM, ARCHIVE,CSV类型的表。下面的测试环境为MySQL 5.6.41,创建测试表,然后对表进行REPAIR TABLE操作

mysql> CREATE TABLE t (
    ->     c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,

    ->     c2 VARCHAR(100),

    ->     c3 VARCHAR(100) )

    -> ENGINE=MyISAM;

Query OK, 0 rows affected (0.01 sec)

 

mysql> SELECT table_name,create_time FROM  information_schema.TABLES WHERE table_name=‘t‘;

+------------+---------------------+

| table_name | create_time         |

+------------+---------------------+

| t          | 2019-10-20 08:35:43 |

+------------+---------------------+

1 row in set (0.00 sec)

然后对表t进行修复操作,发现表的create_time没有变化,如下所示:

mysql> REPAIR TABLE t;
+--------+--------+----------+----------+

| Table  | Op     | Msg_type | Msg_text |

+--------+--------+----------+----------+

| MyDB.t | repair | status   | OK       |

+--------+--------+----------+----------+

1 row in set (0.01 sec)

 

mysql> SELECT table_name,create_time FROM  information_schema.TABLES WHERE table_name=‘t‘;

+------------+---------------------+

| table_name | create_time         |

+------------+---------------------+

| t          | 2019-10-20 08:35:43 |

+------------+---------------------+

1 row in set (0.00 sec)

在另外一个窗口,我们发现索引文件t.MYI的修改时间和状态更改时间都变化了,所以判断索引重建(Index Rebuild)了。

[[email protected] MyDB]# ls -lrt t.*
-rw-rw----. 1 mysql mysql 8608 Oct 20 08:35 t.frm

-rw-rw----. 1 mysql mysql 1024 Oct 20 08:35 t.MYI

-rw-rw----. 1 mysql mysql    0 Oct 20 08:35 t.MYD

[[email protected] MyDB]# stat t.MYI

  File: `t.MYI‘

  Size: 1024            Blocks: 8          IO Block: 4096   regular file

Device: fd00h/64768d    Inode: 1836747     Links: 1

Access: (0660/-rw-rw----)  Uid: (   27/   mysql)   Gid: (   27/   mysql)

Access: 2019-10-20 08:36:02.395428301 +0800

Modify: 2019-10-20 08:35:43.112562600 +0800

Change: 2019-10-20 08:35:43.112562600 +0800

[[email protected] MyDB]# stat t.MYI

  File: `t.MYI‘

  Size: 1024            Blocks: 8          IO Block: 4096   regular file

Device: fd00h/64768d    Inode: 1836747     Links: 1

Access: (0660/-rw-rw----)  Uid: (   27/   mysql)   Gid: (   27/   mysql)

Access: 2019-10-20 08:37:19.686899429 +0800

Modify: 2019-10-20 08:37:10.271475420 +0800

Change: 2019-10-20 08:37:10.271475420 +0800

OPTIMIZE TABLE方法

OPTIMIZE TABLE也可以对索引进行重建,官方文档的介绍如下:

OPTIMIZE TABLE reorganizes the physical storage of table data and associated index data, to reduce storage space and improve I/O efficiency when accessing the table. The exact changes made to each table depend on the storage engine used by that table.

OPTIMIZE TABLE uses online DDL for regular and partitioned InnoDB tables, which reduces downtime for concurrent DML operations. The table rebuild triggered by OPTIMIZE TABLE and performed under the cover by ALTER TABLE ... FORCE is completed in place. An exclusive table lock is only taken briefly during the prepare phase and the commit phase of the operation. During the prepare phase, metadata is updated and an intermediate table is created. During the commit phase, table metadata changes are committed.

OPTIMIZE TABLE rebuilds the table using the table copy method under the following conditions:

·

·         When the old_alter_table system variable is enabled.

·

·         When the server is started with the --skip-new option.

OPTIMIZE TABLE using online DDL is not supported for InnoDB tables that contain FULLTEXT indexes. The table copy method is used instead.

简单来说,OPTIMIZE TABLE操作使用Online DDL模式修改Innodb普通表和分区表,

该方式会在prepare阶段和commit阶段持有表级锁:在prepare阶段修改表的元数据并且创建一个中间表,在commit阶段提交元数据的修改。

由于prepare阶段和commit阶段在整个事务中的时间比例非常小,可以认为该OPTIMIZE TABLE的过程中不影响表的其他并发操作。

测试验证如下,对表t1做了OPTIMIZE TABLE后, 表的创建时间变成了2019-10-20 08:41:57

mysql> OPTIMIZE TABLE t1;
+---------+----------+----------+-------------------------------------------------------------------+

| Table   | Op       | Msg_type | Msg_text                                                          |

+---------+----------+----------+-------------------------------------------------------------------+

| MyDB.t1 | optimize | note     | Table does not support optimize, doing recreate + analyze instead |

| MyDB.t1 | optimize | status   | OK                                                                |

+---------+----------+----------+-------------------------------------------------------------------+

2 rows in set (0.67 sec)

 

mysql> SELECT table_name,create_time FROM  information_schema.TABLES WHERE table_name=‘t1‘;

+------------+---------------------+

| TABLE_NAME | CREATE_TIME         |

+------------+---------------------+

| t1         | 2019-10-20 08:41:57 |

+------------+---------------------+

1 row in set (0.00 sec)

 

  另外,网上有种说法ANALYZE TABLE方法也可以重建索引,其实ANALYZE TABLE是不会对索引进行重建的。测试验证的话,你会发现ibd文件没有变化,表的修改时间/状态更改时间也没有变化。

总结:

测试完后,还是感觉MySQL索引重建的方式怪怪的,可能是有先入为主的观念。总结一下MySQL索引重建的方法:

1: DROP INDEX + RECREATE INDEX.

2: ALTER TABLE方法

3: REPAIR TABLE方法,这种方法对于InnoDB存储引擎的表无效。

4: OPTIMIZE TABLE方法

 

参考资料:

https://dev.mysql.com/doc/refman/8.0/en/rebuilding-tables.html

https://docs.oracle.com/cd/E17952_01/mysql-5.6-en/rebuilding-tables.html

原文地址:https://www.cnblogs.com/kerrycode/p/11706730.html

时间: 2024-10-01 05:11:53

MySQL如何进行索引重建操作?的相关文章

mysql之对索引的操作

1. 为什么使用索引? 数据库对象索引与书的目录非常类似,主要是为了提高从表中检索数据的速度.由于数据储存在数据库表中,所以索引是创建在数据库表对象之上的,由表中的一个字段或多个字段生成的键组成,这些键储存在数据结构(B-树或哈希表)中,通过MySQL可以快速有效的查找与键值相关联的字段.根据索引的储存类型,可以将索引分为B树型索引(BTREE)和哈希索引(HASH). InnoDB和MyISAM储存引擎支持BTREE类型索引,MEMORY储存引擎支持HASH类型索引,默认为BTREE索引. 数

给MySQL字段添加索引的操作

1.添加PRIMARY KEY(主键索引): ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` ) 2.添加UNIQUE(唯一索引) : ALTER TABLE `table_name` ADD UNIQUE ( `column` ) 3.添加INDEX(普通索引) : ALTER TABLE `table_name` ADD INDEX index_name ( `column` ) 4.添加FULLTEXT(全文索引) : ALTER T

MySQL学习笔记-索引操作语句

通过例子来说明如何查看,删除和添加索引,先建立一个表,如下: mysql> create table stu (         -> id int,         -> name char(5),         -> key name(name),         -> unique key id(id)         -> ); 1.查看表的索引(两种方法) (1)show index from 表名; (2)show create table 表名; 2.删

优化、分析Mysql表读写、索引等操作的sql语句效率优化问题

为什么要优化: 随着实际项目的启动,数据库经过一段时间的运行,最初的数据库设置,会与实际数据库运行性能会有一些差异,这时我们 就需要做一个优化调整. 数据库优化这个课题较大,可分为四大类: >主机性能>内存使用性能>网络传输性能>SQL语句执行性能[软件工程师]下面列出一些数据库SQL优化方案: (01)选择最有效率的表名顺序(笔试常考) 数据库的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表将被最先处理,在FROM子句中包含多个表的情况下,你必须选择

Mysql表读写、索引等操作的sql语句效率优化问题

上次我们说到mysql的一些sql查询方面的优化,包括查看explain执行计划,分析索引等等.今天我们分享一些 分析mysql表读写.索引等等操作的sql语句. 闲话不多说,直接上代码: 反映表的读写压力 SELECT file_name AS file, count_read, sum_number_of_bytes_read AS total_read, count_write, sum_number_of_bytes_write AS total_written, (sum_number

MySQL全文索引 FULLTEXT索引和like的区别

1.概要 InnoDB引擎对FULLTEXT索引的支持是MySQL5.6新引入的特性,之前只有MyISAM引擎支持FULLTEXT索引.对于FULLTEXT索引的内容可以使用MATCH()-AGAINST语法进行查询. 为了在InnoDB驱动的表中使用FULLTEXT索引MySQL5.6引入了一些新的配置选项和INFORMATION_SCHEMA表.比如,为了监视一个FULLTEXT索引中文本处理过程的某一方面可以查询INNODB_FT_CONFIG,INNODB_FT_INDEX_TABLE,

mysql B+Tree索引

原文地址:http://blog.codinglabs.org/articles/theory-of-mysql-index.html 数据结构及算法基础 索引的本质 MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构.提取句子主干,就可以得到索引的本质:索引是数据结构. 我们知道,数据库查询是数据库的最主要功能之一.我们都希望查询数据的速度能尽可能的快,因此数据库系统的设计者会从查询算法的角度进行优化.最基本的查询算法当然是顺序查找(linear searc

剖析Mysql的InnoDB索引

摘要: 本篇介绍下Mysql的InnoDB索引相关知识,从各种树到索引原理到存储的细节. InnoDB是Mysql的默认存储引擎(Mysql5.5.5之前是MyISAM,文档).本着高效学习的目的,本篇以介绍InnoDB为主.少量涉及MyISAM作为对照. 这篇文章是我在学习过程中总结完毕的.内容主要来自书本和博客(參考文献会给出).过程中增加了一些自己的理解.描写叙述不准确的地方烦请指出. 1 各种树形结构 本来不打算从二叉搜索树開始,由于网上已经有太多相关文章,可是考虑到清晰的图示对理解问题

mysql中的索引原理与表设计

索引是有效使用数据库的基础,但你的数据量很小的时候,或许通过扫描整表来存取数据的性能还能接受,但当数据量极大时,当访问量极大时,就一定需要通过索引的辅助才能有效地存取数据.一般索引建立的好坏是性能好坏的成功关键. 1.InnoDb数据与索引存储细节 使用InnoDb作为数据引擎的Mysql和有聚集索引的SqlServer的数据存储结构有点类似,虽然在物理层面,他们都存储在Page上,但在逻辑上面,我们可以把数据分为三块:数据区域,索引区域,主键区域,他们通过主键的值作为关联,配合工作.默认配置下