mysql学习笔记(六)

存储引擎(mysql中 特有的)

(86条消息) 我以为我对Mysql事务很熟,直到我遇到了阿里面试官_公号:黎杜编程的博客-CSDN博客

关系数据库表是用于存储和组织信息的数据结构,可以将表理解为由行和列组成的表格,类似于Excel的电子表格的形式。有的表简单,有的表复杂,有的表根本不用来存储任何长期的数据,有的表读取时非常快,但是插入数据时去很差;而我们在实际开发过程中,就可能需要各种各样的表,不同的表,就意味着存储不同类型的数据,数据的处理上也会存在着差异,那么。对于MySQL来说,它提供了很多种类型的存储引擎,我们可以根据对数据处理的需求,选择不同的存储引擎,从而最大限度的利用MySQL强大的功能。这篇博文将总结和分析各个引擎的特点,以及适用场合,并不会纠结于更深层次的东西。我的学习方法是先学会用,懂得怎么用,再去知道到底是如何能用的。下面就对MySQL支持的存储引擎进行简单的介绍。

如何给表去添加存储引擎呢?

show create table t_student;


mysql> show create table t_student;
+-----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table     | Create Table                                                                                                                                                                                                                                                                                                                                     |
+-----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t_student | CREATE TABLE `t_student` (
  `no` int NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `cno` int DEFAULT NULL,
  PRIMARY KEY (`no`),
  KEY `cno` (`cno`),
  CONSTRAINT `t_student_ibfk_1` FOREIGN KEY (`cno`) REFERENCES `t_class` (`classno`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+-----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.12 sec)

在建表的小括号后面可以去给他指定引擎ENGINE,和编码方式CHARSET 

默认的存储引擎是InnoDB

ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

 建表的时候可以指定默认的引擎

mysql> create table t_no(no int primary key)engine=InnoDB default charset=gbk;
Query OK, 0 rows affected (1.20 sec)

mysql支持的存储引擎

 mysql支持九大索引引擎,版本不同支持的引擎不同

mysql> show engines \G
*************************** 1. row ***************************
      Engine: MEMORY
     Support: YES
     Comment: Hash based, stored in memory, useful for temporary tables
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 2. row ***************************
      Engine: MRG_MYISAM
     Support: YES
     Comment: Collection of identical MyISAM tables
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 3. row ***************************
      Engine: CSV
     Support: YES
     Comment: CSV storage engine
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 4. row ***************************
      Engine: FEDERATED
     Support: NO
     Comment: Federated MySQL storage engine
Transactions: NULL
          XA: NULL
  Savepoints: NULL
*************************** 5. row ***************************
      Engine: PERFORMANCE_SCHEMA
     Support: YES
     Comment: Performance Schema
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 6. row ***************************
      Engine: MyISAM
     Support: YES
     Comment: MyISAM storage engine
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 7. row ***************************
      Engine: InnoDB
     Support: DEFAULT
     Comment: Supports transactions, row-level locking, and foreign keys
Transactions: YES
          XA: YES
  Savepoints: YES
*************************** 8. row ***************************
      Engine: BLACKHOLE
     Support: YES
     Comment: /dev/null storage engine (anything you write to it disappears)
Transactions: NO
          XA: NO
  Savepoints: NO
*************************** 9. row ***************************
      Engine: ARCHIVE
     Support: YES
     Comment: Archive storage engine
Transactions: NO
          XA: NO
  Savepoints: NO
9 rows in set (0.72 sec)

MyISAM

MyISAM表是独立于操作系统的,这说明可以轻松地将其从Windows服务器移植到Linux服务器;每当我们建立一个MyISAM引擎的表时,就会在本地磁盘上建立三个文件,文件名就是表明。例如,我建立了一个MyISAM引擎的tb_Demo表,那么就会生成以下三个文件:

1.tb_demo.frm,存储表定义(格式);
2.tb_demo.MYD,存储数据;
3.tb_demo.MYI,存储索引(一本书的目录)。索引可以缩小扫描的范围,提高搜索的效率

MyISAM表无法处理事务,这就意味着有事务处理需求的表,不能使用MyISAM存储引擎。MyISAM存储引擎特别适合在以下几种情况下使用:

1.选择密集型的表。MyISAM存储引擎在筛选大量数据时非常迅速,这是它最突出的优点。
2.插入密集型的表。MyISAM的并发插入特性允许同时选择和插入数据。例如:MyISAM存储引擎很适合管理邮件或Web服务器日志数据

InnoDB

InnoDB是一个健壮的事务型存储引擎(非常安全),这种存储引擎已经被很多互联网公司使用,为用户操作非常大的数据存储提供了一个强大的解决方案。我的电脑上安装的MySQL 5.6.13版,InnoDB就是作为默认的存储引擎。InnoDB还引入了行级锁定和外键约束,在以下场合下,使用InnoDB是最理想的选择:

1.更新密集的表。InnoDB存储引擎特别适合处理多重并发的更新请求。
2.事务。InnoDB存储引擎是支持事务的标准MySQL存储引擎。
3.自动灾难恢复。与其它存储引擎不同,InnoDB表能够自动从灾难中恢复。
4.外键约束。MySQL支持外键的存储引擎只有InnoDB。
5.支持自动增加列AUTO_INCREMENT属性。

一般来说,如果需要事务支持,并且有较高的并发读取频率,InnoDB是不错的选择。

MEMORY

使用MySQL Memory存储引擎的出发点是速度。为得到最快的响应时间,采用的逻辑存储介质是系统内存。虽然在内存中存储表数据确实会提供很高的性能,但当mysqld守护进程崩溃时,所有的Memory数据都会丢失。获得速度的同时也带来了一些缺陷。它要求存储在Memory数据表里的数据使用的是长度不变的格式,这意味着不能使用BLOB和TEXT这样的长度可变的数据类型,VARCHAR是一种长度可变的类型,但因为它在MySQL内部当做长度固定不变的CHAR类型,所以可以使用。查询效率是最高的,因为是放在内存里面的,内存是直接取出来的,光速,不需要和硬盘进行交互。

事务(重点,五颗星)

一个事务就是一个完整的业务逻辑,假设转账,从A账户转账到B账户10000块钱,A账户金钱少10000块钱,B账户的金钱多10000块钱,这就是一个完整的事务逻辑。最小的工作单元,要么成功,要么失败。

 只有DML insert  delete update 和事务逻辑有关,一个事务就是多条DML语句同时成功,或者同时失败

提交事务:

清空日志文件,将数据全部彻底提交到数据库表当中。commit;

回滚事务:

将之前的DML语句事务全部撤销,并且清空日志文件。rollback;

事务transaction

mysql默认情况下是自动提交事务的,每次执行一次DML则会直接提交,而回滚只能回滚到上一次的提交点。

mysql> select * from t_vip;
+----+--------+
| id | name   |
+----+--------+
|  1 | liming |
|  2 | liming |
|  3 | liming |
|  4 | liming |
|  5 | liming |
|  6 | liming |
|  7 | liming |
|  8 | liming |
|  9 | liming |
| 10 | liming |
+----+--------+
10 rows in set (0.01 sec)

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t_vip(name) values('liming');
Query OK, 1 row affected (0.06 sec)

mysql> insert into t_vip(name) values('liming');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t_vip(name) values('liming');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t_vip(name) values('liming');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t_vip(name) values('liming');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t_vip(name) values('liming');
Query OK, 1 row affected (0.00 sec)

mysql> rollback;
Query OK, 0 rows affected (0.18 sec)

mysql> select * from t_vip;
+----+--------+
| id | name   |
+----+--------+
|  1 | liming |
|  2 | liming |
|  3 | liming |
|  4 | liming |
|  5 | liming |
|  6 | liming |
|  7 | liming |
|  8 | liming |
|  9 | liming |
| 10 | liming |
+----+--------+
10 rows in set (0.00 sec)

事务特性(4种):

原子性 (atomicity):强调事务的不可分割.(已经是最小的单元)
一致性 (consistency):事务的执行的前后数据的完整性保持一致.(同时成功或者同时失败)
隔离性 (isolation):一个事务执行的过程中,不应该受到其他事务的干扰(A事务和B事务有一定的隔离)多线程操纵一张表
持久性(durability) :事务一旦结束,数据就持久到数据库(相当于将没有保存到硬盘上的数据保存到硬盘上)
事务运行模式(3种)

自动提交事务:默认事务管理模式。如果一个语句成功地完成,则提交该语句;如果遇到错误,则回滚该语句。
显式事务:以BEGIN TRANSACTION显式开始,以COMMIT或ROLLBACK显式结束。
隐性事务:当连接以此模式进行操作时,sql将在提交或回滚当前事务后自动启动新事务。无须描述事务的开始,只需提交或回滚每个事务。它生成连续的事务链。
 

事务的隔离性

A教室和B教室之间有一道墙,这道墙可以很厚,也可以很薄,这就是事务的隔离特性。

第一种隔离级别:Read uncommitted(读未提交)最低的隔离级别
如果一个事务已经开始写数据,则另外一个事务不允许同时进行写操作,但允许其他事务读此行数据,该隔离级别可以通过“排他写锁”,但是不排斥读线程实现。这样就避免了更新丢失,却可能出现脏读,也就是说事务B读取到了事务A未提交的数据

解决了更新丢失,但还是可能会出现脏读(读到了脏数据)

大多数数据库都是二档起步

第二种隔离级别:Read committed(读提交)
如果是一个读事务(线程),则允许其他事务读写,如果是写事务将会禁止其他事务访问该行数据,该隔离级别避免了脏读,但是可能出现不可重复读。事务A事先读取了数据,事务B紧接着更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。(每一次读到的数据都是绝对的真实)Oracle默认的隔离级别是读已提交

解决了更新丢失和脏读问题

第三种隔离级别:Repeatable read(可重复读取)(提交事务之后也读不到,读取的都是开启事务之后的数据)
可重复读取是指在一个事务内,多次读同一个数据,在这个事务还没结束时,其他事务不能访问该数据(包括了读写),这样就可以在同一个事务内两次读到的数据是一样的,因此称为是可重复读隔离级别,读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务(包括了读写),这样避免了不可重复读和脏读,但是有时可能会出现幻读。(读取数据的事务)可以通过“共享读镜”和“排他写锁”实现。

案例:银行里执行一条select语句在下午1点-3点,但是期间还是有人取钱。

解决了更新丢失、脏读、不可重复读、但是还会出现幻读

第四种隔离级别:Serializable(可序化)最高的隔离级别
提供严格的事务隔离,它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行,如果仅仅通过“行级锁”是无法实现序列化的,必须通过其他机制保证新插入的数据不会被执行查询操作的事务访问到。序列化是最高的事务隔离级别,同时代价也是最高的,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻读

解决了更新丢失、脏读、不可重复读、幻读(虚读)
 

隔离级别演示:

验证:read uncommittedd

验证:read committed

验证:repeatable read

验证:serializable

查看事务级别:select @@tx_isolation mysql8之后改成了其他的 transcation_isolation

 read uncommitted

mysql> select @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ         |
+-------------------------+
1 row in set (0.08 sec)



#验证读未提交
事务1:
mysql> select @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ         |
+-------------------------+
1 row in set (0.08 sec)

mysql> set global transaction isolation level read uncommitted;
Query OK, 0 rows affected (0.25 sec)

mysql>  use bjpowernode;
Database changed
mysql> select * from t_vip;
+----+--------+
| id | name   |
+----+--------+
|  1 | liming |
|  2 | liming |
|  3 | liming |
|  4 | liming |
|  5 | liming |
|  6 | liming |
|  7 | liming |
|  8 | liming |
|  9 | liming |
| 10 | liming |
+----+--------+
10 rows in set (0.17 sec)

mysql> select * from t_vip;
+----+--------+
| id | name   |
+----+--------+
|  1 | liming |
|  2 | liming |
|  3 | liming |
|  4 | liming |
|  5 | liming |
|  6 | liming |
|  7 | liming |
|  8 | liming |
|  9 | liming |
| 10 | liming |
| 17 | lihong |
+----+--------+
11 rows in set (0.01 sec)
事务2:
mysql> use bjpowernode;
Database changed
mysql> show tables;
+-----------------------+
| Tables_in_bjpowernode |
+-----------------------+
| dept                  |
| emp                   |
| emp2                  |
| salgrade              |
| t_class               |
| t_customer            |
| t_no                  |
| t_student             |
| t_user                |
| t_vip                 |
+-----------------------+
10 rows in set (0.43 sec)

mysql> select * from t_vip;
+----+--------+
| id | name   |
+----+--------+
|  1 | liming |
|  2 | liming |
|  3 | liming |
|  4 | liming |
|  5 | liming |
|  6 | liming |
|  7 | liming |
|  8 | liming |
|  9 | liming |
| 10 | liming |
+----+--------+
10 rows in set (0.10 sec)

mysql> insert into t_vip(name) values('lihong');
Query OK, 1 row affected (0.64 sec)

mysql> select * from t_vip;
+----+--------+
| id | name   |
+----+--------+
|  1 | liming |
|  2 | liming |
|  3 | liming |
|  4 | liming |
|  5 | liming |
|  6 | liming |
|  7 | liming |
|  8 | liming |
|  9 | liming |
| 10 | liming |
| 17 | lihong |
+----+--------+
11 rows in set (0.00 sec)

 read committed:

事务2提交之后事务1才可以看到
事务1:
mysql> select * from @@transaction_isolation;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@@transaction_isolation' at line 1
mysql> select @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| READ-COMMITTED          |
+-------------------------+
1 row in set (0.00 sec)

mysql> use bipowernode;
ERROR 1049 (42000): Unknown database 'bipowernode'
mysql> use bjpowernode;
Database changed
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t_vip;
+----+--------+
| id | name   |
+----+--------+
|  1 | liming |
|  2 | liming |
|  3 | liming |
|  4 | liming |
|  5 | liming |
|  6 | liming |
|  7 | liming |
|  8 | liming |
|  9 | liming |
| 10 | liming |
| 17 | lihong |
+----+--------+
11 rows in set (0.00 sec)

mysql> select * from t_vip;
+----+--------+
| id | name   |
+----+--------+
|  1 | liming |
|  2 | liming |
|  3 | liming |
|  4 | liming |
|  5 | liming |
|  6 | liming |
|  7 | liming |
|  8 | liming |
|  9 | liming |
| 10 | liming |
| 17 | lihong |
+----+--------+
11 rows in set (0.03 sec)

mysql> select * from t_vip;
+----+--------------+
| id | name         |
+----+--------------+
|  1 | liming       |
|  2 | liming       |
|  3 | liming       |
|  4 | liming       |
|  5 | liming       |
|  6 | liming       |
|  7 | liming       |
|  8 | liming       |
|  9 | liming       |
| 10 | liming       |
| 11 | xiaotiantian |
| 17 | lihong       |
+----+--------------+
12 rows in set (0.00 sec)


事务2:

mysql> select @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| READ-COMMITTED          |
+-------------------------+
1 row in set (0.00 sec)

mysql> use bipowernode;
ERROR 1049 (42000): Unknown database 'bipowernode'
mysql> use bjpowernode;
Database changed
mysql> select * from t_vip;
+----+--------+
| id | name   |
+----+--------+
|  1 | liming |
|  2 | liming |
|  3 | liming |
|  4 | liming |
|  5 | liming |
|  6 | liming |
|  7 | liming |
|  8 | liming |
|  9 | liming |
| 10 | liming |
| 17 | lihong |
+----+--------+
11 rows in set (0.00 sec)

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t_vip;
+----+--------+
| id | name   |
+----+--------+
|  1 | liming |
|  2 | liming |
|  3 | liming |
|  4 | liming |
|  5 | liming |
|  6 | liming |
|  7 | liming |
|  8 | liming |
|  9 | liming |
| 10 | liming |
| 17 | lihong |
+----+--------+
11 rows in set (0.00 sec)

mysql> insert into t_vip values(11,'xiaotiantian');
Query OK, 1 row affected (0.01 sec)

mysql> select * from t_vip;
+----+--------------+
| id | name         |
+----+--------------+
|  1 | liming       |
|  2 | liming       |
|  3 | liming       |
|  4 | liming       |
|  5 | liming       |
|  6 | liming       |
|  7 | liming       |
|  8 | liming       |
|  9 | liming       |
| 10 | liming       |
| 11 | xiaotiantian |
| 17 | lihong       |
+----+--------------+
12 rows in set (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.07 sec)

 repeatable read;

只要事务1开启之后,其他的事务的操作commit之后都是幻向
事务1:
C:\Users\王率宇>mysql -uroot -pwsy
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 34
Server version: 8.0.28 MySQL Community Server - GPL

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> set global transaction isolation level repeatable read;
Query OK, 0 rows affected (0.00 sec)

mysql> exit
Bye

C:\Users\王率宇>mysql -uroot -pwsy
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 35
Server version: 8.0.28 MySQL Community Server - GPL

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> use bjpowernode;
Database changed
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t_vip;
+----+--------------+
| id | name         |
+----+--------------+
|  1 | liming       |
|  2 | liming       |
|  3 | liming       |
|  4 | liming       |
|  5 | liming       |
|  6 | liming       |
|  7 | liming       |
|  8 | liming       |
|  9 | liming       |
| 10 | liming       |
| 11 | xiaotiantian |
| 17 | lihong       |
+----+--------------+
12 rows in set (0.01 sec)

mysql> select * from t_vip;
+----+--------------+
| id | name         |
+----+--------------+
|  1 | liming       |
|  2 | liming       |
|  3 | liming       |
|  4 | liming       |
|  5 | liming       |
|  6 | liming       |
|  7 | liming       |
|  8 | liming       |
|  9 | liming       |
| 10 | liming       |
| 11 | xiaotiantian |
| 17 | lihong       |
+----+--------------+
12 rows in set (0.00 sec)

mysql> 就是事务2已经commit了;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '就是事务2已经commit了' at line 1
mysql> select * from t_vip;
+----+--------------+
| id | name         |
+----+--------------+
|  1 | liming       |
|  2 | liming       |
|  3 | liming       |
|  4 | liming       |
|  5 | liming       |
|  6 | liming       |
|  7 | liming       |
|  8 | liming       |
|  9 | liming       |
| 10 | liming       |
| 11 | xiaotiantian |
| 17 | lihong       |
+----+--------------+
12 rows in set (0.00 sec)









事务2:
mysql> select @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ         |
+-------------------------+
1 row in set (0.00 sec)

mysql> use bjpowernode;
Database changed
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t_vip;
+----+--------------+
| id | name         |
+----+--------------+
|  1 | liming       |
|  2 | liming       |
|  3 | liming       |
|  4 | liming       |
|  5 | liming       |
|  6 | liming       |
|  7 | liming       |
|  8 | liming       |
|  9 | liming       |
| 10 | liming       |
| 11 | xiaotiantian |
| 17 | lihong       |
+----+--------------+
12 rows in set (0.01 sec)

mysql> insert into t_vip(12,'duoraimi');
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '12,'duoraimi')' at line 1
mysql> insert into t_vip values(12,'duoraimi');
Query OK, 1 row affected (0.01 sec)

mysql> commit;
Query OK, 0 rows affected (0.26 sec)

 SERIALIZABLE:事务1没结束之前事务2就不能动

#事务1结束之后 事务2才可以动

事务1
mysql> set global transaction isolation level serializable;
Query OK, 0 rows affected (0.00 sec)

mysql> use bjpowenode;
ERROR 1049 (42000): Unknown database 'bjpowenode'
mysql> use bjpowernode;
Database changed
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t_vip(13,'xiaomoxian');
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '13,'xiaomoxian')' at line 1
mysql> insert into t_vip values(13,'xiaomoxian');
Query OK, 1 row affected (0.01 sec)

mysql> commit;
Query OK, 0 rows affected (0.10 sec)


事务2:
mysql> select @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| SERIALIZABLE            |
+-------------------------+
1 row in set (0.00 sec)

mysql> use bjpowernode;
Database changed
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t_vip;
+----+--------------+
| id | name         |
+----+--------------+
|  1 | liming       |
|  2 | liming       |
|  3 | liming       |
|  4 | liming       |
|  5 | liming       |
|  6 | liming       |
|  7 | liming       |
|  8 | liming       |
|  9 | liming       |
| 10 | liming       |
| 11 | xiaotiantian |
| 12 | duoraimi     |
| 13 | xiaomoxian   |
| 17 | lihong       |
+----+--------------+
14 rows in set (18.19 sec)

索引:

(70条消息) 一文搞懂MySQL索引(清晰明了)_Free Joe的博客-CSDN博客_mysql索引

MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度。

打个比方,如果合理的设计且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是一个人力三轮车。

拿汉语字典的目录页(索引)打比方,我们可以按拼音、笔画、偏旁部首等排序的目录(索引)快速查找到需要的字。

索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引,即一个索引包含多个列。

创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。

实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。

上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点:虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。

建立索引会占用磁盘空间的索引文件。

(70条消息) MySQL索引实现原理分析_代码搬运工.的博客-CSDN博客_mysql索引原理

1.在mysql当中有主键的地儿会自动去创建索引,然后有unique约束的也会去创建索引。

2.在数据库当中每一条记录咋磁盘当中都会有记号

3.在mysq1当中,索引是一个单独的对象,不同的存储引擎以不同的形式存在,在MyISAM存储引擎中,索引存储在一个.MYI文件中。在InnoDB存储引擎中索引存储在一个逻辑名称叫做tablespace的当中。在MEMORY存储引擎当中索引被存储在内存当中。不管索引存储在哪里,索引在mysq1当中都是一个树的形式存在。(自平衡二二叉树: B-Tree )

 

 

 添加索引的条件:

1.数据量非常大

2.该字段经常出现在where后面,经常以条件的形式存在

3.该字段出现很少的DML语句,因为经过DML语句之后,索引需要重新排序

建议不要随意去添加索引,因为索引如果太多的话,是需要去维护的也会降低使用的性能

 创建和删除索引:

mysql> use bjpowernode;
Database changed
mysql> show tables;
+-----------------------+
| Tables_in_bjpowernode |
+-----------------------+
| dept                  |
| emp                   |
| emp2                  |
| salgrade              |
| t_class               |
| t_customer            |
| t_no                  |
| t_student             |
| t_user                |
| t_vip                 |
+-----------------------+
10 rows in set (0.23 sec)

mysql> select * from emp;
+-------+--------+-----------+------+------------+---------+---------+--------+
| EMPNO | ENAME  | JOB       | MGR  | HIREDATE   | SAL     | COMM    | DEPTNO |
+-------+--------+-----------+------+------------+---------+---------+--------+
|  7369 | SMITH  | CLERK     | 7902 | 1980-12-17 |  800.00 |    NULL |     20 |
|  7499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 | 1600.00 |  300.00 |     30 |
|  7521 | WARD   | SALESMAN  | 7698 | 1981-02-22 | 1250.00 |  500.00 |     30 |
|  7566 | JONES  | MANAGER   | 7839 | 1981-04-02 | 2975.00 |    NULL |     20 |
|  7654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 | 1250.00 | 1400.00 |     30 |
|  7698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 | 2850.00 |    NULL |     30 |
|  7782 | CLARK  | MANAGER   | 7839 | 1981-06-09 | 2450.00 |    NULL |     10 |
|  7788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 | 3000.00 |    NULL |     20 |
|  7839 | KING   | PRESIDENT | NULL | 1981-11-17 | 5000.00 |    NULL |     10 |
|  7844 | TURNER | SALESMAN  | 7698 | 1981-09-08 | 1500.00 |    0.00 |     30 |
|  7876 | ADAMS  | CLERK     | 7788 | 1987-05-23 | 1100.00 |    NULL |     20 |
|  7900 | JAMES  | CLERK     | 7698 | 1981-12-03 |  950.00 |    NULL |     30 |
|  7902 | FORD   | ANALYST   | 7566 | 1981-12-03 | 3000.00 |    NULL |     20 |
|  7934 | MILLER | CLERK     | 7782 | 1982-01-23 | 1300.00 |    NULL |     10 |
+-------+--------+-----------+------+------------+---------+---------+--------+
14 rows in set (0.04 sec)


# 创建索引
mysql> create index emp_ename_index on emp(ename);
Query OK, 0 rows affected (1.24 sec)
Records: 0  Duplicates: 0  Warnings: 0

# 删除索引
mysql> drop index emp_ename_index on emp;
Query OK, 0 rows affected (0.37 sec)
Records: 0  Duplicates: 0  Warnings: 0
# 查看是否使用了索引

mysql> explain select * from emp where ename = 'king';
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | emp   | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   14 |    10.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.05 sec)
# 这里的rows 为14  说明没有使用索引 type为All


# 创建索引
create index emp_ename_index on emp(ename);


mysql> create index emp_ename_index on emp(ename);\\
Query OK, 0 rows affected (0.41 sec)
Records: 0  Duplicates: 0  Warnings: 0



mysql> explain select ename from emp where ename='king';
+----+-------------+-------+------------+------+-----------------+-----------------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys   | key             | key_len | ref   | rows | filtered | Extra       |
+----+-------------+-------+------------+------+-----------------+-----------------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | emp   | NULL       | ref  | emp_ename_index | emp_ename_index | 43      | const |    1 |   100.00 | Using index |
+----+-------------+-------+------------+------+-----------------+-----------------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
#下面的就发生变化了,这里的rows变成了1,并且type变成了ref
#底层是有哈希算法的

索引的失效:

(71条消息) 索引失效和注意事项_ka_ko的博客-CSDN博客_索引失效

(71条消息) MySQL索引原理、失效情况_不吃西红柿丶的博客-CSDN博客_mysql索引失效原理

1.模糊查询的时候会全表查询,有时候则会失效

select * from emp where ename = '%T';

 2.使用or的时候,两边必须都有索引才会走索引,否则就会失效

mysql> explain select ename from emp where ename='smith' or job='clerk';
+----+-------------+-------+------------+------+-----------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys   | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+-----------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | emp   | NULL       | ALL  | emp_ename_index | NULL | NULL    | NULL |   14 |    16.43 | Using where |
+----+-------------+-------+------------+------+-----------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.11 sec)

3.失效的第三种情况

 使用复合索引,没有使用左边的列,索引失效(这个左边的列指的是创建的时候,左边的列)

mysql> create index emp_job_sal_index on emp(sal,job);
Query OK, 0 rows affected (0.71 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> explain select ename from emp where sal='800';
+----+-------------+-------+------------+------+-------------------+-------------------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys     | key               | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+------+-------------------+-------------------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | emp   | NULL       | ref  | emp_job_sal_index | emp_job_sal_index | 9       | const |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+------+-------------------+-------------------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.10 sec)

mysql> explain select ename from emp where job='clerk';
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | emp   | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   14 |    10.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

4.失效的第四种情况,在wehere后面索引的字段出现了计算

mysql> create index emp_sal_index on emp(sal);
Query OK, 0 rows affected (0.40 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> explain select ename from emp where sal=800;
+----+-------------+-------+------------+------+---------------------------------+-------------------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys                   | key               | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------------------------+-------------------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | emp   | NULL       | ref  | emp_job_sal_index,emp_sal_index | emp_job_sal_index | 9       | const |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------------------------+-------------------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

mysql> explain select ename from emp where sal*2=800;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | emp   | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   14 |   100.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.04 sec)

 5.在索引的字段里面使用了函数

mysql> explain select ename from emp where lower(ename)='smith';
+----+-------------+-------+------------+-------+---------------+-----------------+---------+------+------+----------+--------------------------+
| id | select_type | table | partitions | type  | possible_keys | key             | key_len | ref  | rows | filtered | Extra                    |
+----+-------------+-------+------------+-------+---------------+-----------------+---------+------+------+----------+--------------------------+
|  1 | SIMPLE      | emp   | NULL       | index | NULL          | emp_ename_index | 43      | NULL |   14 |   100.00 | Using where; Using index |
+----+-------------+-------+------------+-------+---------------+-----------------+---------+------+------+----------+--------------------------+
1 row in set, 1 warning (0.00 sec)

索引的分类: 

索引是优化的时候首要要考虑的,复合索引,单一索引,主键索引,唯一性索引

 

视图:

(71条消息) MySQL视图_pan_junbiao的博客-CSDN博客_mysql视图

view:站在不同的角度去看待同一份问题

创建视图对象,删除视图对象

# 创建视图对象
create view '名称' as DQL的语句;
# 删除视图
drop view '名称';

通过对视图的增删改查可以操作原来的表 

mysql> create view dept2_view as select * from dept2;
Query OK, 0 rows affected (0.21 sec)

mysql> select * from dept2_view;
+--------+------------+----------+
| DEPTNO | DNAME      | LOC      |
+--------+------------+----------+
|     10 | ACCOUNTING | NEW YORK |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  |
|     40 | OPERATIONS | BOSTON   |
+--------+------------+----------+
4 rows in set (0.10 sec)

mysql> insert into dept2_view(deptno,dname,loc) values(50,'TEACHER','SHANGHAI');
Query OK, 1 row affected (0.25 sec)

mysql> select * from dept2;
+--------+------------+----------+
| DEPTNO | DNAME      | LOC      |
+--------+------------+----------+
|     10 | ACCOUNTING | NEW YORK |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  |
|     40 | OPERATIONS | BOSTON   |
|     50 | TEACHER    | SHANGHAI |
+--------+------------+----------+
5 rows in set (0.00 sec)

视图是用来简化DQL语句的,就不用出现多个语句,这样会很长,不好操作

mysql> create view emp_dept_view as select e.ename,e.sal,d.dname from emp e join dept d on e.deptno=d.deptno;
Query OK, 0 rows affected (0.31 sec)

一句很长的SQL语句需要在很多地方去调用,编写起来很麻烦每次,则就可以编写一个VIEW试图语句来方便调用。

视图对象存储在硬盘上不会丢失。

mysql数据导出,导入

#数据导出
mysqldumb bjpowernode > '路径/....sql' -uroot -pwsy;
#数据导入
create database bjpowernode;
use bjpowernode;
Source D:/bjpowernode.sql;

数据库设计的三范式:

(72条消息) 数据库设计需遵守的三大范式_程序员小冷的博客-CSDN博客_数据库必须满足第几范式

数据库设计的依据,可以避免数据库的冗余,数据的浪费

第一范式:当关系模式R的所有属性都不能在分解为更基本的数据单位时,称R是满足第一范式的,简记为1NF。满足第一范式是关系模式规范化的最低要求,否则,将有很多基本操作在这样的关系模式中实现不了。(有主键,每个字段原子性不可拆分)

一对一,外键唯一

 2. 第二范式:要求一个表中只能存储一种数据,需要确保数据库表中的每一列都和主键相关
每一行的数据只能与其中一列相关,即一行数据只做一件事。只要数据列中出现数据重复,就要把表拆分开来,两列的属性相近或相似或一样,尽量合并属性一样的列,确保不产生冗余数据。
反例:如以下表出现冗余,不符合第二范式。(不可以产生部份依赖,会产生冗余

多对多,三张表,关系表,两个外键 

3. 第三范式:需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。(不要产生传递依赖)

 一对多,两张表,多的表加外键

 有的时候会拿冗余来换速度,考虑实际的开发需求

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值