1. 程式人生 > 其它 >網際網路行業中最常用的資料庫——MySQL 索引、事務與儲存引擎

網際網路行業中最常用的資料庫——MySQL 索引、事務與儲存引擎

一、MySQL 索引

1.1 索引的概念

索引是一個排序的列表,在這個列表中儲存著索引的值和包含這個值的資料所在行的實體地址(類似於C語言的連結串列通過指標指向資料記錄的記憶體地址)。
使用索引後可以不用掃描全表來定位某行的資料,而是先通過索引表找到該行資料對應的實體地址然後訪問相應的資料,因此能加快資料庫的查詢速度。
索引就好比是一本書的目錄,可以根據目錄中的頁碼快速找到所需的內容。
索引是表中一列或者若干列值排序的方法。
建立索引的目的是加快對錶中記錄的查詢或排序。

1.2 索引的作用及缺點

1.2.1 優點

設定了合適的索引之後,資料庫利用各種快速定位技術,能夠大大加快查詢速度,這是建立所有的最主要的原因。
當表很大或查詢涉及到多個表時,使用索引可以成千上萬倍地提高查詢速度。
可以降低資料庫的IO成本,並且索引還可以降低資料庫的排序成本。
通過建立唯一性索引,可以保證資料表中每一行資料的唯一性。
可以加快表與表之間的連線。
在使用分組和排序時,可大大減少分組和排序的時間。

1.2.2 缺點

索引需要佔用額外的磁碟空間。
對於 MyISAM 引擎而言,索引檔案和資料檔案是分離的,索引檔案用於儲存資料記錄的地址。
而 InnoDB 引擎的表資料檔案本身就是索引檔案。
在插入和修改資料時要花費更多的時間,因為索引也要隨之變動。

1.3 建立索引的原則依據

索引隨可以提升資料庫查詢的速度,但並不是任何情況下都適合建立索引。因為索引本身會消耗系統資源,在有索引的情況下,資料庫會先進行索引查詢,然後定位到具體的資料行,如果索引使用不當,反而會增加資料庫的負擔。

表的主鍵、外來鍵必須有索引。因為主鍵具有唯一性,外來鍵關聯的是子表的主鍵,查詢時可以快速定位。
記錄數超過300行的表應該有索引。如果沒有索引,需要把表遍歷一遍,會嚴重影響資料庫的效能。
經常與其他表進行連線的表,在連線欄位上應該建立索引。
唯一性太差的欄位不適合建立索引。
更新太頻繁地欄位不適合建立索引。
經常出現在 where 子句中的欄位,特別是大表的欄位,應該建立索引。
索引應該建在選擇性高的欄位上。
索引應該建在小欄位上,對於大的文字欄位甚至超長欄位,不要建索引。

1.4 索引的分類和建立

1.4.1 普通索引

最基本的索引型別,沒有唯一性之類的限制。

●直接建立索引

CREATE INDEX 索引名 ON 表名 (列名[(length)]);

#(列名(length)):length是可選項,下同。如果忽略 length 的值,則使用整個列的值作為索引。如果指定使用列前的 length 個字元來建立索引,這樣有利於減小索引檔案的大小。
#索引名建議以“_index”結尾。

●修改表方式建立

ALTER TABLE 表名 ADD INDEX 索引名 (列名);

●建立表的時候指定索引

CREATE TABLE 表名 ( 欄位1 資料型別,欄位2 資料型別[,...],INDEX 索引名 (列名));

1.4.2 唯一索引

與普通索引類似,但區別是唯一索引列的每個值都唯一。唯一索引允許有空值(注意和主鍵不同)。如果是用組合索引建立,則列值的組合必須唯一。新增唯一鍵將自動建立唯一索引。

●直接建立唯一索引:

CREATE UNIQUE INDEX 索引名 ON 表名(列名);

●修改表方式建立唯一索引:

ALTER TABLE 表名 ADD UNIQUE 索引名 (列名);

●建立表的時候指定唯一索引:

CREATE TABLE 表名 (欄位1 資料型別,欄位2 資料型別[,...],UNIQUE 索引名 (列名));

1.4.3 主鍵索引

是一種特殊的唯一索引,必須指定為“PRIMARY KEY”。一個表只能有一個主鍵,不允許有空值。 新增主鍵將自動建立主鍵索引。

●建立表的時候指定主鍵索引

CREATE TABLE 表名 ([...],PRIMARY KEY (列名));


●修改表方式建立主鍵索引

ALTER TABLE 表名 ADD PRIMARY KEY (列名); 

1.4.4 組合索引(單列索引與多列索引)

可以是單列上建立的索引,也可以是在多列上建立的索引。需要滿足最左原則,因為 select 語句的 where 條件是依次從左往右執行的,所以在使用 select 語句查詢時 where 條件使用的欄位順序必須和組合索引中的排序一致,否則索引將不會生效。

CREATE TABLE 表名 (列名1 資料型別,列名2 資料型別,列名3 資料型別,INDEX 索引名 (列名1,列名2,列名3));

select * from 表名 where 列名1='...' AND 列名2='...' AND 列名3='...';

1.4.5 全文索引(FULLTEXT)

適合在進行模糊查詢的時候使用,可用於在一篇文章中檢索文字資訊。在 MySQL5.6 版本以前。

●直接建立全文索引

CREATE FULLTEXT INDEX 索引名 ON 表名 (列名);

●修改表方式建立全文索引

ALTER TABLE 表名 ADD FULLTEXT 索引名 (列名);


●建立表的時候指定全文索引

CREATE TABLE 表名 (欄位1 資料型別[,...],FULLTEXT 索引名 (列名));

#資料型別可以為 CHAR、VARCHAR 或者 TEXT

●使用全文索引查詢

SELECT * FROM 表名 WHERE MATCH(列名) AGAINST('查詢內容');

1.5 檢視索引

show index from 表名;
show keys from 表名;

各欄位的含義如下:

欄位 含義
Table 表的名稱
Non_unique 如果索引不能包括重複詞,則為 0;如果可以,則為 1
Key_name 索引的名稱
Seq_in_index 索引中的列序號,從 1 開始
Column_name 列名稱
Collation 列以什麼方式儲存在索引中。在 MySQL 中,有值‘A’(升序)或 NULL(無分類)
Cardinality 索引中唯一值數目的估計值
Sub_part 如果列只是被部分地編入索引,則為被編入索引的字元的數目。如果整列被編入索引,則為 NULL
Packed 指示關鍵字如何被壓縮。如果沒有被壓縮,則為 NULL
Null 如果列含有 NULL,則含有 YES。如果沒有,則該列含有 NO
Index_type 用過的索引方法(BTREE, FULLTEXT, HASH, RTREE)
Comment 備註

1.6 刪除索引

●直接刪除索引

DROP INDEX 索引名 ON 表名;

●修改表方式刪除索引

ALTER TABLE 表名 DROP INDEX 索引名;


●刪除主鍵索引

ALTER TABLE 表名 DROP PRIMARY KEY;

二、MySQL事務

2.1 事務的概念

事務是一種機制、一個操作序列,包含了一組資料庫操作命令,並且把所有的命令作為一個整體一起向系統提交或撤銷操作請求,即這一組資料庫命令要麼都執行,要麼都不執行。
事務是一個不可分割的工作邏輯單元,在資料庫系統上執行併發操作時,事務是最小的控制單元。
事務適用於多使用者同時操作的資料庫系統的場景,如銀行、保險公司及證券交易系統等等。
事務通過事務的整體性以保證資料的一致性。
總的來說,事務就是是一個操作序列,這些操作要麼都執行,要麼都不執行,它是一個不可分割的工作單位。

2.2 事務的ACID特點

ACID,是指在可靠資料庫管理系統(DBMS)中,事務(transaction)應該具有的四個特性:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、永續性(Durability)。這是可靠資料庫所應具備的幾個特性。

2.2.1 原子性

指事務是一個不可再分割的工作單位,事務中的操作要麼都發生,要麼都不發生。

事務是一個完整的操作,事務的各元素是不可分的。
事務中的所有元素必須作為一個整體提交或回滾。
如果事務中的任何元素失敗,則整個事務將失敗。

2.2.2 一致性

指在事務開始之前和事務結束以後,資料庫的完整性約束沒有被破壞。

當事務完成時,資料必須處於一致狀態。
在事務開始前,資料庫中儲存的資料處於一致狀態。
在正在進行的事務中,資料可能處於不一致的狀態。
當事務成功完成時,資料必須再次回到已知的一致狀態。

2.2.3 隔離性

指在併發環境中,當不同的事務同時操縱相同的資料時,每個事務都有各自的完整資料空間。

對資料進行修改的所有併發事務是彼此隔離的,表明事務必須是獨立的,它不應以任何方式依賴於或影響其他事務。
修改資料的事務可在另一個使用相同資料的事務開始之前訪問這些資料,或者在另一個使用相同資料的事務結束之後訪問這些資料。
事務之間的相互影響分為幾種,分別為:
(1)髒讀:一個事務讀取了另一個事務未提交的資料,而這個資料是有可能回滾的。

(2)不可重複讀:一個事務內兩個相同的查詢卻返回了不同資料。這是由於查詢時系統中其他事務修改的提交而引起的。

(3)幻讀:一個事務對一個表中的資料進行了修改,這種修改涉及到表中的全部資料行。同時,另一個事務也修改這個表中的資料,這種修改是向表中插入一行新資料。那麼,操作前一個事務的使用者會發現表中還有沒有修改的資料行,就好象發生了幻覺一樣。

(4)丟失更新:兩個事務同時讀取同一條記錄,A先修改記錄,B也修改記錄(B不知道A修改過),B提交資料後B的修改結果覆蓋了A的修改結果。

Mysql 及事物隔離級別:
(1)read_uncommitted : 讀取尚未提交的資料 :不解決髒讀

(2)read_committed:讀取已經提交的資料 :可以解決髒讀

(3)repeatable_read:重讀讀取:可以解決髒讀 和 不可重複讀 —mysql預設的

(4)serializable:序列化:可以解決 髒讀 不可重複讀 和 虛讀—相當於鎖表

mysql預設的事務處理級別是 repeatable read ,而Oracle和SQL Server是 read committed 。

事務隔離級別 髒讀 不可重複讀 幻讀 第一類丟失更新 第二類丟失更新
read uncommitted 允許 允許 允許 禁止 允許
read committed 禁止 允許 允許 禁止 允許
repeatable read 禁止 禁止 允許 禁止 禁止
serializable 禁止 禁止 禁止 禁止 禁止
● 查詢全域性事務隔離級別:

show global variables like '%isolation%';
SELECT @@global.tx_isolation;


● 查詢會話事務隔離級別:

show session variables like '%isolation%';
SELECT @@session.tx_isolation; 
SELECT @@tx_isolation;

● 設定全域性事務隔離級別:

set global transaction isolation level read committed;

● 設定會話事務隔離級別:

set session transaction isolation level read committed;


2.2.4 永續性

在事務完成以後,該事務所對資料庫所作的更改便持久的儲存在資料庫之中,並不會被回滾。

指不管系統是否發生故障,事務處理的結果都是永久的。
一旦事務被提交,事務的效果會被永久地保留在資料庫中。

2.2.5 總結

在事務管理中,原子性是基礎,隔離性是手段,一致性是目的,永續性是結果。

2.3 事務控制語句

BEGIN 或 START TRANSACTION:顯式地開啟一個事務。

COMMIT 或 COMMIT WORK:提交事務,並使已對資料庫進行的所有修改變為永久性的。

ROLLBACK 或 ROLLBACK WORK:回滾會結束使用者的事務,並撤銷正在進行的所有未提交的修改。

SAVEPOINT S1:使用 SAVEPOINT 允許在事務中建立一個回滾點,一個事務中可以有多個 SAVEPOINT;“S1”代表回滾點名稱。

ROLLBACK TO [SAVEPOINT] S1:把事務回滾到標記點。

例項:實驗測試事務控制語句

第一步:建立表和資料

1)測試begin和commit(開始事務和提交事務)

2)測試事務未提交的回滾
3)測試建立回滾點並進行回滾

2.4 使用 set 設定控制事務

SET AUTOCOMMIT=0;#禁止自動提交(狀態為OFF)

SET AUTOCOMMIT=1;#開啟自動提交,Mysql預設為1(狀態為ON)
SHOW VARIABLES LIKE ‘AUTOCOMMIT’;#檢視Mysql中的AUTOCOMMIT值

如果沒有開啟自動提交,當前會話連線的mysql的所有操作都會當成一個事務直到你輸入rollback|commit;當前事務才算結束。當前事務結束前新的mysql連線時無法讀取到任何當前會話的操作結果。

如果開起了自動提交,mysql會把每個sql語句當成一個事務,然後自動的commit。

當然無論開啟與否,begin; commit|rollback; 都是獨立的事務。

三、MySQL儲存引擎

3.1 MyISAM 表支援的3 種不同的儲存格式

3.1.1 靜態(固定長度)表

靜態表是預設的儲存格式。靜態表中的欄位都是非可變欄位,這樣每個記錄都是固定長度的,這種儲存方式的優點是儲存非常迅速,容易快取,出現故障容易恢復;缺點是佔用的空間通常比動態表多。

3.1.2 動態表

動態表包含可變欄位,記錄不是固定長度的,這樣儲存的優點是佔用空間較少,但是頻繁的更新、刪除記錄會產生碎片,需要定期執行 OPTIMIZE TABLE 語句或 myisamchk -r 命令來改善效能,並且出現故障的時候恢復相對比較困難。

3.1.3 壓縮表

壓縮表由 myisamchk 工具建立,佔據非常小的空間,因為每條記錄都是被單獨壓縮的,所以只有非常小的訪問開支。

3.2 控制語句

1)檢視系統支援的儲存引擎

show engines;

2)查看錶使用的儲存引擎
方法一:

show table status from 庫名 where name='表名'\g

方法二:

use 庫名;
show create table 表名;

)修改儲存引擎

① 通過 alter table 修改

use 庫名;
alter table 表名 engine=MyISAM


② 通過修改 /etc/my.cnf 配置檔案,指定預設儲存引擎並重啟服務

vim /etc/my.cnf
......
[mysqld]
......
default-storage-engine=INNODB
systemctl restart mysql.service

注意:此方法只對修改了配置檔案並重啟mysql服務後新建立的表有效,已經存在的表不會有變更。

③ 通過 create table 建立表時指定儲存引擎

use 庫名;
create table 表名(欄位1 資料型別,...) engine=MyISAM;