MySQL如何進行索引重建操做?

在MySQL數據庫中,沒有相似於SQL Server數據庫或Oracle數據庫中索引重建的語法(ALTER INDEX ... REBUILD),那麼在MySQL數據庫中,是否有什麼方式重建索引呢? 在官方文檔中"2.11.10 Rebuilding or Repairing Tables or Indexes"中,提到下面三種方式能夠Rebuild Indexhtml

 

·         Dump and Reload Methodnode

 

·         ALTER TABLE Methodmysql

 

·         REPAIR TABLE Methodsql

 

 

另外, 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方法oracle

 

這種方法過於簡單,這裏不敘說了。其實也沒有啥好說的。app

 

 

 

ALTER TABLE方法測試

 

 

那麼咱們可否在MySQL中找到索引的建立或修改時間呢?通過查證,目前而言,MySQL中是沒有相關係統表或視圖會記錄索引的建立時間的,咱們能夠用間接的方法來間接驗證,有些方法不是特別可靠和準確,最準確的方法應該是閱讀源碼:ui

 

 

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表就是重建表的意思),因此索引也等價於從新建立了。

 

 

clip_image001

 

 

在另一個窗口,咱們對比t1.ibd的建立時間,以下所示,也間接驗證了表和索引都REBUILD了。(這裏是MySQL 8.0.18 ,若是是以前的版本,還有frm之類的文件。)

 

 

 
[root@db-server MyDB]# ls -lrt t1*
-rw-r-----. 1 mysql mysql 131072 Oct 20 08:18 t1.ibd
[root@db-server 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: -
[root@db-server 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: -

 

clip_image002

 

 

 

 

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)

 

 

clip_image003

 

 

在另一個窗口,咱們發現索引文件t.MYI的修改時間和狀態更改時間都變化了,因此判斷索引重建(Index Rebuild)了。

 

 

[root@testlnx02 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
[root@testlnx02 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
[root@testlnx02 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

相關文章
相關標籤/搜索