1. 程式人生 > 資料庫 >mysql索引 、事務與儲存引擎

mysql索引 、事務與儲存引擎

mysql索引 、事務與儲存引擎

索引的概念

資料庫索引

1、是一個排序的列表,儲存著索引值和這個值所對應的實體地址
2、無須對整個表進行掃描,通過實體地址就可以找到所需資料
3、是表中—列或者若干列值排序的方法
4、需要額外的磁碟空間

索引的作用

1、資料庫利用各種快速定位技術,能夠大大加快查詢速率
2、當表很大或查詢涉及到多個表時,可以成千上萬倍地提高查詢速度
3、可以降低資料庫的IO成本,並且還可以降低資料庫的排序成本
4、通過建立唯─性索引保證資料表資料的唯━性
5、可以加快表與表之間的連線
6、在使用分組和排序時,可大大減少分組和排序時間

建立索引的原則依據

1、表的主鍵、外來鍵必須有索引 ##外來鍵:主表中的外來鍵是另一張表的主鍵
2、記錄數超過300行的表應該有索引
3、經常與其他表進行連線的表,在連線欄位上應該建立索引
4、唯一性太差的欄位不適合建立索引
5、更新太頻繁的欄位不適合建立索引
6、經常出現在where字句中的欄位,特別是大表的欄位,應該建立索引
7、索引應該建在選擇性高的欄位上
8、索引應該建在小欄位上,對於大的文字欄位甚至超長欄位,不要建索引

索引的分類

普通索引、唯一索引、主鍵索引、組合索引、全文索引。
索引的建立
1、直接建立索引
2、修改表結構方式新增索引
3、建立表結構時建立索引

檢視索引方法

檢視索引語法

方法一:show index from 表名

方法二:show keys from 表名

刪除索引的語法

方法一:drop index 索引名 on 表名
方法二:alter table 表名 drop index 索引名

普通索引
最基本的索引型別,沒有唯一性之類的限制
建立普通索引的方式
1、直接建立索引
mysql> show tables;
+---------------+
| Tables_in_aaa |
+---------------+
| cj            |
| cj2           |
+---------------+
2 rows in set (0.00 sec)

mysql> desc cj;
+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| id    | int(10)      | NO   | PRI | NULL    | auto_increment |
| age   | int(3)       | NO   |     | NULL    |                |
| name  | varchar(128) | NO   |     | NULL    |                |
| score | decimal(5,0) | YES  |     | NULL    |                |
| addr  | int(3)       | YES  |     | NULL    |                |
+-------+--------------+------+-----+---------+----------------+
5 rows in set (0.01 sec)
mysql> create index putong on cj(age);  //給cj表裡的age建立putong索引
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show index from cj\G;  //檢視cj表裡面的索引
*************************** 1. row ***************************
        Table: cj
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: id
    Collation: A
  Cardinality: 4
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
*************************** 2. row ***************************
        Table: cj
   Non_unique: 1
     Key_name: putong
 Seq_in_index: 1
  Column_name: age
    Collation: A
  Cardinality: 3
     Sub_part: NULL
       Packed: NULL
         Null: 
   Index_type: BTREE
      Comment: 
Index_comment: 
2 rows in set (0.00 sec)

ERROR: 
No query specified

mysql> 

mysql> drop index putong on cj;  //刪除cj表裡的索引
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show keys from cj;  //檢視cj裡面的索引
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| cj    |          0 | PRIMARY  |            1 | id          | A         |           4 |     NULL | NULL   |      | BTREE      |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)

mysql> 

2、修改表時新增
mysql> alter table cj add index putong2(name);
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show index from cj;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| cj    |          0 | PRIMARY  |            1 | id          | A         |           4 |     NULL | NULL   |      | BTREE      |         |               |
| cj    |          1 | putong2  |            1 | name        | A         |           4 |     NULL | NULL   |      | BTREE      |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec)

mysql> 


3、 建立表時新增索引
mysql> create table stu(num int(6) not null primary key, name varchar(64) not null, age int(3) not null, index putong3(name));
Query OK, 0 rows affected (0.02 sec)

mysql> show index from stu;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| stu   |          0 | PRIMARY  |            1 | num         | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
| stu   |          1 | putong3  |            1 | name        | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.01 sec)

mysql> 

唯一索引
與普通索引基本相同
與普通索引的區別是索引列的所有值只能出現一次。即必須唯一
建立唯一索引的方式
1、直接建立
mysql> insert into stu values(201001,'zhangsan',18),(201002,'lisi',18),(201003,'zhangsan',17),(201004,'wangwu',19);
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> select *from stu;
+--------+----------+-----+
| num    | name     | age |
+--------+----------+-----+
| 201001 | zhangsan |  18 |
| 201002 | lisi     |  18 |
| 201003 | zhangsan |  17 |
| 201004 | wangwu   |  19 |
+--------+----------+-----+
4 rows in set (0.00 sec)

mysql> create unique index one on stu (name);
ERROR 1062 (23000): Duplicate entry 'zhangsan' for key 'one'  //姓名zhangsan相同不讓建
mysql> create unique index one on stu (age);
ERROR 1062 (23000): Duplicate entry '18' for key 'one'   //年齡18相同不讓建
mysql> create unique index one on stu (num);   //num沒有相同值  可以建
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0


2、修改表時建立索引
mysql> drop index one on stu;  //刪除索引
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> alter table stu add unique two(num);  給num新增索引two
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show index from stu;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| stu   |          0 | PRIMARY  |            1 | num         | A         |           4 |     NULL | NULL   |      | BTREE      |         |               |
| stu   |          0 | two      |            1 | num         | A         |           4 |     NULL | NULL   |      | BTREE      |         |               |
| stu   |          1 | putong3  |            1 | name        | A         |           3 |     NULL | NULL   |      | BTREE      |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
3 rows in set (0.00 sec)

mysql> 



3、 建立表時新增索引

mysql> create table book(id int(6),book_name varchar(64),sta int(1),unique song(id));  //建立book表 給id新增song索引
Query OK, 0 rows affected (0.02 sec)

mysql> show index from book;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| book  |          0 | song     |            1 | id          | A         |           0 |     NULL | NULL   | YES  | BTREE      |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)

mysql> 


主鍵索引
是一種特殊的唯一索引,指定為‘PRIMARY KEY’
一個表只能有一個主鍵,不允許有空值
建立主鍵索引的方法


mysql> insert into stu (name,age) values('liming',18);
ERROR 1364 (HY000): Field 'num' doesn't have a default value  //不允許有空值 num沒有配值

mysql> drop index song on book;  
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0


mysql> alter table book add primary key(book_name);
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show index from book;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| book  |          0 | PRIMARY  |            1 | book_name   | A         |           1 |     NULL | NULL   |      | BTREE      |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.01 sec)

mysql> 


組合索引(單列索引與多列索引)
可以是單列上建立的索引,也可以是多列上建立索引
最左原則,從左往右依次執行
建立組合索引的方式

mysql> create table song(id int(3), name char(32) not null, age int(3) not null,index song(id,name,age));  //給song表裡面的id name age建立索引
Query OK, 0 rows affected (0.01 sec)

mysql> show index from song;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| song  |          1 | song     |            1 | id          | A         |           0 |     NULL | NULL   | YES  | BTREE      |         |               |
| song  |          1 | song     |            2 | name        | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
| song  |          1 | song     |            3 | age         | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
3 rows in set (0.00 sec)

mysql> 

全文索引
mysql從3.23.23版本開始支援全文索引和全文檢索
索引型別為FULLTEXT
可以在char 、varchar或者text型別的列上建立

mysql> create fulltext index name on cj(name);  //cj表中name新增name索引
Query OK, 0 rows affected, 1 warning (0.07 sec)
Records: 0  Duplicates: 0  Warnings: 1

mysql> show index from cj;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| cj    |          0 | PRIMARY  |            1 | id          | A         |           4 |     NULL | NULL   |      | BTREE      |         |               |
| cj    |          1 | name     |            1 | name        | NULL      |           4 |     NULL | NULL   |      | FULLTEXT   |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec)

事務的概念

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

事務的ACID特點

原子性(Atomicity)

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

一致性(Consistency)

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

隔離性(Isolation)

1、對資料進行修改的所有併發事務是彼此隔離的,表明事務必須是獨立的,它不應以任何方式依賴於或影響其他事務
2、修改資料的事務可在另一個使用相同資料的事務開始之前訪問這些資料,或者在另一個使用相同資料的事務結束之後訪問這些資料

永續性(Durability)

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

事務控制語句

MySQL事務預設是自動提交的,當SQL語句提交時事務便自動提交

控制語句

begin或start transaction
commit
rollback
savepoint indetifier 建立儲存點
release savepoint identifier 刪除一個儲存點
rollback to identifier 回滾到儲存點
set transaction 設定事務的隔離級別

事務控制方法

手動對事務進行控制的方法
1、事務處理命令控制事務
begin:開始一個事務
rollback:回滾一個事務
commit:提交一個事務
2、使用set命令進行控制
set autocommit=0:禁止自動提交
set autocommit=1:開啟自動提交(預設開啟)

儲存引擎的概念

1、定義:MySQL中的資料用各種不同的技術儲存在檔案中,每一種技術都使用不同的儲存機制、索引技巧、鎖定水平並最終提供不同的功能和能力,這些不同的技術以及配套的功能在MySQL中稱為儲存引擎

2、儲存引擎就是 MySQL將資料儲存在檔案系統中的儲存方式或者儲存格式

3、目前 MySQL常用的兩種儲存引擎
MyISAM
InnoDB
4、MySQL儲存引擎是 MySQL資料庫伺服器中的元件,負責為資料庫執行實際的資料I/O操作
5、MySQL系統中,儲存引擎處於檔案系統之上,在資料儲存到資料檔案之前會傳輸到儲存引擎,之後按照各個儲存引擎的儲存格式進行儲存

MyISAM的特點

1、MylSAM不支援事務,也不支援外來鍵

2、訪問速度快

3、對事務完整性沒有要求

4、MyISAM在磁碟上儲存成三個檔案
(1)儲存檔案:副檔名為.frm
(2)資料檔案:副檔名為.MYD (MYData)
(3)索引檔案:副檔名是.MYI (MYIndex)

5、表級鎖定形式,資料在更新時鎖定整個表

6、資料庫在讀寫過程中相互阻塞(讀寫不能同時進行)

7、資料單獨寫入或讀取,速度過程較快且佔用資源相對少

8、MyISAM支援的儲存格式
靜態表
動態表
壓縮表

MyISAM適用的生產場景

公司業務不需要事務的支援
單方面讀取或寫入資料比較多的業務
MyISAM儲存引擎資料讀寫都比較頻繁場景不適合
使用讀寫併發訪問相對較低的業務
資料修改相對較少的業務
對資料業務一致性要求不是非常高的業務
伺服器硬體資源相對比較差

lnnoDB特點

支援4個事務隔離級別
行級鎖定,但是全表掃描仍然會是表級鎖定
讀寫阻塞與事務隔離級別相關
能非常高效的快取索引和資料
表與主鍵以簇的方式儲存
支援分割槽、表空間,類似oracle資料庫
支援外來鍵約束,5.5前不支援全文索引,5.5後支援全文索引
對硬體資源要求還是比較高的場合

InnoDB適用生產場景

1、業務需要事務的支援
2、行級鎖定對高併發有很好的適應能力,但需確保查詢是通過索引來完成
3、業務資料更新較為頻繁的場景
·如:論壇,微博等
4、業務資料一致性要求較高
·如:銀行業務
5、硬體裝置記憶體較大,利用Innodb較好的快取能力來提高記憶體利用率,減少磁碟IO的壓力

企業選擇儲存引擎依據

1、需要考慮每個儲存引擎提供的核心功能及應用場景
2、支援的欄位和資料型別
(1)所有引擎都支援通用的資料型別
(2)但不是所有的引擎都支援其它的欄位型別,如二進位制物件
3、鎖定型別:不同的儲存引擎支援不同級別的鎖定
(1)表鎖定
(2)行鎖定
4、索引的支援
(1)建立索引在搜尋和恢復資料庫中的資料時能顯著提高效能
(2)不同的儲存引擎提供不同的製作索引的技術
(3)有些儲存引擎根本不支援索引
5、事務處理的支援
(1)提高在向表中國更新和插入資訊期間的可靠性
(2)可根據企業業務是否要支援事務選擇儲存引擎

修改儲存引擎

方法1: alter table修改
alter table table_ name engine=引擎;

mysql> show engines\G //檢視儲存引擎
mysql> show create table cj\G   //檢視cj表的狀態
mysql> alter table cj engine=MyISAM;  //修改cj引擎
Query OK, 4 rows affected (0.02 sec)
Records: 4  Duplicates: 0  Warnings: 0

方法2:
修改my.cnf,指定預設儲存引擎並重啟服務
default- storage-engine=InnoDB

[root@server1 ~]# vi /etc/my.cnf
default-storage-engine=MyISAM
[root@server1 ~]# systemctl restart mysqld  //重啟mysql
[root@server1 ~]# mysql
mysql> show engines\G  //檢視儲存引擎
*************************** 5. row ***************************
      Engine: MyISAM
     Support: DEFAULT
     Comment: MyISAM storage engine
Transactions: NO
          XA: NO
  Savepoints: NO

![在這裡插入圖片描述](https://www.icode9.com/img/ll/?i=20201225122227282.png?,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81MDM0NTA1OQ==,size_16,color_FFFFFF,t_70)


方法3: create table建立表時指定儲存引擎
create table表名 (欄位) engine=引擎

mysql> use aaa;
mysql> create table song10(id int(1)) engine=InnoDB;  //建立表格時指定引擎
Query OK, 0 rows affected (0.01 sec)