文章目录
- 1、什么是MySQL?
- 2、数据库三大范式是什么
- 3、MySQL的binlog有有几种录入格式?分别有什么区别?
- 4、mysql有哪些数据类型
- 5、MySQL存储引擎MyISAM与InnoDB区别
- 6、MyISAM索引与InnoDB索引的区别
- 7、存储引擎选择
- 8、什么是索引
- 9、索引有哪些优缺点
- 10、索引有哪几种类型
- 11、索引的数据结构(b树,hash)
- 12、索引的基本原理
- 13、索引算法有哪些
- 14、索引设计的原则
- 15、创建索引的原则
- 16、创建索引时需要注意什么
- 17、使用索引查询一定能提高查询的性能吗?为什么
- 18、前缀索引
- 19、什么是最左前缀原则?什么是最左匹配原则
- 20、B树和B+树的区别
- 21、Hash索引和B+树所有有什么区别
- 22、数据库为什么使用B+树而不是B树
- 23、什么是聚簇索引?
- 24、何时使用聚簇索引与非聚簇索引
- 25、联合索引是什么?为什么需要注意联合索引中的顺序?
- 事务
- 26、 什么是数据库事务
- 27、事物的四大特性(ACID)
- 28、什么是脏读?幻读?不可重复读?
- 29、什么是事务的隔离级别?MySQL的默认隔离级别是什么?
- 30、按照锁的粒度分数据库锁有哪些
- 31、从锁的类别上分MySQL都有哪些锁呢
- 32、数据库的乐观锁和悲观锁是什么?怎么实现的?
- sql优化
1、什么是MySQL?
MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一。在Java企业级开发中非常常用,因为 MySQL 是开源免费的,并且方便扩展。
2、数据库三大范式是什么
第一范式:每个列都不可以再拆分。
第二范式:在第一范式的基础上,非主键列完全依赖于主键,而不能是依赖于主键的一部分。
第三范式:在第二范式的基础上,非主键列只依赖于主键,不依赖于其他非主键。
在设计数据库结构的时候,要尽量遵守三范式,如果不遵守,必须有足够的理由。比如性能。事实上我们经常会为了性能而妥协数据库的设计。
3、MySQL的binlog有有几种录入格式?分别有什么区别?
有三种格式,statement,row和mixed。
statement模式下,每一条会修改数据的sql都会记录在binlog中。不需要记录每一行的变化,减少了binlog日志量,节约了IO,提高性能。由于sql的执行是有上下文的,因此在保存的时候需要保存相关的信息,同时还有一些使用了函数之类的语句无法被记录复制。
row级别下,不记录sql语句上下文相关信息,仅保存哪条记录被修改。记录单元为每一行的改动,基本是可以全部记下来但是由于很多操作,会导致大量行的改动(比如alter table),因此这种模式的文件保存的信息太多,日志量太大。
mixed,一种折中的方案,普通操作使用statement记录,当无法使用statement的时候使用row。
此外,新版的MySQL中对row级别也做了一些优化,当表结构发生变化的时候,会记录语句而不是逐行记录。
4、mysql有哪些数据类型
整数类型,包括TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,分别表示1字节、2字节、3字节、4字节、8字节整数。任何整数类型都可以加上UNSIGNED属性,表示数据是无符号的,即非负整数。
长度:整数类型可以被指定长度,例如:INT(11)表示长度为11的INT类型。长度在大多数场景是没有意义的,它不会限制值的合法范围,只会影响显示字符的个数,而且需要和UNSIGNED ZEROFILL属性配合使用才有意义。
例子,假定类型设定为INT(5),属性为UNSIGNED ZEROFILL,如果用户插入的数据为12的话,那么数据库实际存储数据为00012。
2、实数类型,包括FLOAT、DOUBLE、DECIMAL。
DECIMAL可以用于存储比BIGINT还大的整型,能存储精确的小数。
而FLOAT和DOUBLE是有取值范围的,并支持使用标准的浮点进行近似计算。
计算时FLOAT和DOUBLE相比DECIMAL效率更高一些,DECIMAL你可以理解成是用字符串进行处理。
3、字符串类型,包括VARCHAR、CHAR、TEXT、BLOB
VARCHAR用于存储可变长字符串,它比定长类型更节省空间。
VARCHAR使用额外1或2个字节存储字符串长度。列长度小于255字节时,使用1字节表示,否则使用2字节表示。
VARCHAR存储的内容超出设置的长度时,内容会被截断。
CHAR是定长的,根据定义的字符串长度分配足够的空间。
CHAR会根据需要使用空格进行填充方便比较。
CHAR适合存储很短的字符串,或者所有值都接近同一个长度。
CHAR存储的内容超出设置的长度时,内容同样会被截断。
使用策略:
对于经常变更的数据来说,CHAR比VARCHAR更好,因为CHAR不容易产生碎片。
对于非常短的列,CHAR比VARCHAR在存储空间上更有效率。
使用时要注意只分配需要的空间,更长的列排序时会消耗更多内存。
尽量避免使用TEXT/BLOB类型,查询时会使用临时表,导致严重的性能开销。
4、枚举类型(ENUM),把不重复的数据存储为一个预定义的集合。
有时可以使用ENUM代替常用的字符串类型。
ENUM存储非常紧凑,会把列表值压缩到一个或两个字节。
ENUM在内部存储时,其实存的是整数。
尽量避免使用数字作为ENUM枚举的常量,因为容易混乱。
排序是按照内部存储的整数
5、日期和时间类型,尽量使用timestamp,空间效率高于datetime,
用整数保存时间戳通常不方便处理。
如果需要存储微妙,可以使用bigint存储。
5、MySQL存储引擎MyISAM与InnoDB区别
6、MyISAM索引与InnoDB索引的区别
- InnoDB索引是聚簇索引,MyISAM索引是非聚簇索引。
- InnoDB的主键索引的叶子节点存储着行数据,因此主键索引非常高效。
- MyISAM索引的叶子节点存储的是行数据地址,需要再寻址一次才能得到数据。
- InnoDB非主键索引的叶子节点存储的是主键和其他带索引的列数据,因此查询时做到覆盖索引会非常高效。
7、存储引擎选择
如果没有特别的需求,使用默认的Innodb即可。
MyISAM:以读写插入为主的应用程序,比如博客系统、新闻门户网站。
Innodb:更新(删除)操作频率也高,或者要保证数据的完整性;并发量高,支持事务和外键。比如OA自动化办公系统。
8、什么是索引
索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。
索引是一种数据结构。数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B树及其变种B+树。
更通俗的说,索引就相当于目录。为了方便查找书中的内容,通过对内容建立索引形成目录。索引是一个文件,它是要占据物理空间的。
9、索引有哪些优缺点
一、索引的优点
- 可以大大加快数据的检索速度,这也是创建索引的最主要的原因。
- 通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。
二、索引的缺点
- 时间方面:创建索引和维护索引要耗费时间,具体地,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,会降低增/改/删的执行效率;
- 空间方面:索引需要占物理空间。
10、索引有哪几种类型
1、主键索引: 数据列不允许重复,不允许为NULL,一个表只能有一个主键。
2、唯一索引: 数据列不允许重复,允许为NULL值,一个表允许多个列创建唯一索引。
可以通过 ALTER TABLE table_name ADD UNIQUE (column); 创建唯一索引
可以通过 ALTER TABLE table_name ADD UNIQUE (column1,column2); 创建唯一组合索引
3、普通索引: 基本的索引类型,没有唯一性的限制,允许为NULL值。
可以通过ALTER TABLE table_name ADD INDEX index_name (column);创建普通索引
可以通过ALTER TABLE table_name ADD INDEX index_name(column1, column2, column3);创建组合索引
4、全文索引: 是目前搜索引擎使用的一种关键技术。
可以通过ALTER TABLE table_name ADD FULLTEXT (column);创建全文索引
11、索引的数据结构(b树,hash)
索引的数据结构和具体存储引擎的实现有关,在MySQL中使用较多的索引有Hash索引,B+树索引等,而我们经常使用的InnoDB存储引擎的默认索引实现为:B+树索引。对于哈希索引来说,底层的数据结构就是哈希表,因此在绝大多数需求为单条记录查询的时候,可以选择哈希索引,查询性能最快;其余大部分场景,建议选择BTree索引。
1)B树索引
mysql通过存储引擎取数据,基本上90%的人用的就是InnoDB了,按照实现方式分,InnoDB的索引类型目前只有两种:BTREE(B树)索引和HASH索引。B树索引是Mysql数据库中使用最频繁的索引类型,基本所有存储引擎都支持BTree索引。通常我们说的索引不出意外指的就是(B树)索引(实际是用B+树实现的,因为在查看表索引时,mysql一律打印BTREE,所以简称为B树索引)
B+tree性质:
1、n棵子tree的节点包含n个关键字,不用来保存数据而是保存数据的索引。
2、所有的叶子结点中包含了全部关键字的信息,及指向含这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。
3、所有的非终端结点可以看成是索引部分,结点中仅含其子树中的最大(或最小)关键字。
4、B+ 树中,数据对象的插入和删除仅在叶节点上进行。
5、B+树有2个头指针,一个是树的根节点,一个是最小关键码的叶节点。
2哈希索引
简要说下,类似于数据结构中简单实现的HASH表(散列表)一样,当我们在mysql中用哈希索引时,主要就是通过Hash算法(常见的Hash算法有直接定址法、平方取中法、折叠法、除数取余法、随机数法),将数据库字段数据转换成定长的Hash值,与这条数据的行指针一并存入Hash表的对应位置;如果发生Hash碰撞(两个不同关键字的Hash值相同),则在对应Hash键下以链表形式存储。当然这只是简略模拟图。
12、索引的基本原理
索引用来快速地寻找那些具有特定值的记录。如果没有索引,一般来说执行查询时遍历整张表。
索引的原理很简单,就是把无序的数据变成有序的查询
1、把创建了索引的列的内容进行排序
2、对排序结果生成倒排表
3、在倒排表内容上拼上数据地址链
4、在查询的时候,先拿到倒排表内容,再取出数据地址链,从而拿到具体数据
13、索引算法有哪些
1、BTree算法
BTree是最常用的mysql数据库索引算法,也是mysql默认的算法。因为它不仅可以被用在=,>,>=,<,<=和between这些比较操作符上,而且还可以用于like操作符,只要它的查询条件是一个不以通配符开头的常量, 例如:
-- 只要它的查询条件是一个不以通配符开头的常量
select * from user where name like 'jack%';
-- 如果一通配符开头,或者没有使用常量,则不会使用索引,例如:
select * from user where name like '%jack';
2、Hash算法
Hash Hash索引只能用于对等比较,例如=,<=>(相当于=)操作符。由于是一次定位数据,不像BTree索引需要从根节点到枝节点,最后才能访问到页节点这样多次IO访问,所以检索效率远高于BTree索引。
14、索引设计的原则
- 适合索引的列是出现在where子句中的列,或者连接子句中指定的列
- 基数较小的类,索引效果较差,没有必要在此列建立索引
- 使用短索引,如果对长字符串列进行索引,应该指定一个前缀长度,这样能够节省大量索引空间
- 不要过度索引。索引需要额外的磁盘空间,并降低写操作的性能。在修改表内容的时候,索引会进行更新甚至重构,索引列越多,这个时间就会越长。所以只保持需要的索引有利于查询即可。
15、创建索引的原则
索引虽好,但也不是无限制的使用,最好符合一下几个原则
1) 最左前缀匹配原则,组合索引非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。
2)较频繁作为查询条件的字段才去创建索引
3)更新频繁字段不适合创建索引
4)若是不能有效区分数据的列不适合做索引列(如性别,男女未知,最多也就三种,区分度实在太低)
5)尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。
6)定义有外键的数据列一定要建立索引。
7)对于那些查询中很少涉及的列,重复值比较多的列不要建立索引。
8)对于定义为text、image和bit的数据类型的列不要建立索引。
16、创建索引时需要注意什么
- 非空字段:应该指定列为NOT NULL,除非你想存储NULL。在mysql中,含有空值的列很难进行查询优化,因为它们使得索引、索引的统计信息以及比较运算更加复杂。你应该用0、一个特殊的值或者一个空串代替空值;
- 取值离散大的字段:(变量各个取值之间的差异程度)的列放到联合索引的前面,可以通过count()函数查看字段的差异值,返回值越大说明字段的唯一值越多字段的离散程度高;
- 索引字段越小越好:数据库的数据存储以页为单位一页存储的数据越多一次IO操作获取的数据越大效率越高。
17、使用索引查询一定能提高查询的性能吗?为什么
使用索引不一定能提高查询性能。
问题
- 索引维护成本高,数据修改时需维护索引,频繁修改时可能成性能瓶颈。
- 过多索引占用空间、降低写入性能,且可能让查询优化器选错索引。
- 不适合的查询条件下,索引可能无用甚至降低性能。
- 所以,是否使用索引需根据具体场景和数据特点综合考虑。
18、前缀索引
语法:index(field(10))
,使用字段值的前10个字符建立索引,默认是使用字段的全部内容建立索引。
前提:前缀的标识度高。比如密码就适合建立前缀索引,因为密码几乎各不相同。
实操的难度:在于前缀截取的长度。
我们可以利用select count(*)/count(distinct left(password,prefixLen));
,通过从调整prefixLen的值(从1自增)查看不同前缀长度的一个平均匹配度,接近1时就可以了(表示一个密码的前prefixLen个字符几乎能确定唯一一条记录)
19、什么是最左前缀原则?什么是最左匹配原则
- 顾名思义,就是最左优先,在创建多列索引时,要根据业务需求,where子句中使用最频繁的一列放在最左边。
- 最左前缀匹配原则,非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。
- =和in可以乱序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式
20、B树和B+树的区别
在B树中,你可以将键和值存放在内部节点和叶子节点;但在B+树中,内部节点都是键,没有值,叶子节点同时存放键和值。
B+树的叶子节点有一条链相连,而B树的叶子节点各自独立。
1、使用B树的好处
B树可以在内部节点同时存储键和值,因此,把频繁访问的数据放在靠近根节点的地方将会大大提高热点数据的查询效率。这种特性使得B树在特定数据重复多次查询的场景中更加高效。
2、使用B+树的好处
由于B+树的内部节点只存放键,不存放值,因此,一次读取,可以在内存页中获取更多的键,有利于更快地缩小查找范围。 B+树的叶节点由一条链相连,因此,当需要进行一次全数据遍历的时候,B+树只需要使用O(logN)时间找到最小的一个节点,然后通过链进行O(N)的顺序遍历即可。而B树则需要对树的每一层进行遍历,这会需要更多的内存置换次数,因此也就需要花费更多的时间
21、Hash索引和B+树所有有什么区别
Hash索引
1. 工作原理
Hash索引使用哈希表作为其底层数据结构。哈希表通过哈希函数将索引键值映射到一个固定大小的数组中,从而实现快速的数据访问。在理想情况下,哈希索引可以提供常数时间复杂度的查询性能(O(1))。
2. 优点
快速查找:对于等值查询(例如WHERE column = value),Hash索引可以提供极快的查找速度。
简单结构:哈希表的结构相对简单,易于实现和管理。
3. 缺点
不支持范围查询:Hash索引不支持范围查询(例如WHERE column > value),因为哈希函数不保留键值的顺序。
哈希冲突:如果哈希函数产生冲突,需要额外的处理机制(如链地址法),这可能会影响性能。
不支持排序:由于哈希表不保持键值的顺序,因此无法支持排序操作。
B+树索引
1. 工作原理
B+树索引是一种多路平衡查找树,它保持数据有序,并支持快速的查找、插入和删除操作。B+树的非叶子节点存储索引键值和指向子节点的指针,而叶子节点存储实际的数据记录。
2. 优点
支持范围查询:B+树索引支持高效的范围查询,因为数据是有序存储的。
高度平衡:B+树保持树的高度平衡,确保查询操作的时间复杂度稳定。
顺序访问友好:B+树的叶子节点通过链表连接,便于顺序访问和排序操作。
3. 缺点
插入和删除开销:B+树的插入和删除操作可能需要调整树的结构,这可能会带来额外的开销。
空间利用率:B+树的非叶子节点不存储数据,可能会导致空间利用率略低于哈希索引。
22、数据库为什么使用B+树而不是B树
(1)B+树空间利用率更高,可减少I/O次数
一般来说,索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。这样的话,索引查找过程中就要产生磁盘I/O消耗。而因为B+树的内部节点只是作为索引使用,而不像B树那样每个节点都需要存储硬盘指针。也就是说:B+树中每个非叶节点没有指向某个关键字具体信息的指针,所以每一个节点可以存放更多的关键字数量,即一次性读入内存所需要查找的关键字也就越多,减少了I/O操作。
e.g.
假设磁盘中的一个盘块容纳16bytes,而一个关键字2bytes,一个关键字具体信息指针2bytes。一棵9阶B-tree(一个结点最多8个关键字)的内 部结点需要2个盘快。而B+ 树内部结点只需要1个盘快。当需要把内部结点读入内存中的时候,B 树就比B+ 树多一次盘块查找时间(在磁盘中是盘片旋转的时间)。
(2)增删文件(节点)时,效率更高
因为B+树的叶子节点包含所有关键字,并以有序的链表结构存储,这样可很好提高增删效率,基于范围查询更好。
(3)B+树的查询效率更加稳定
因为B+树的每次查询过程中,都需要遍历从根节点到叶子节点的某条路径。所有关键字的查询路径长度相同,导致每一次查询的效率相当。
关于B 树与 B+树
B树
每个节点都存储key和data,所有节点组成这棵树,并且叶子节点指针为null。
B+树
只有叶子节点存储data,叶子节点包含了这棵树的所有键值,叶子节点不存储指针。
后来又在B+树上增加了顺序访问指针,也就是每个叶子节点增加一个指向相邻叶子节点的指针,这样一棵树成了数据库系统实现索引的首选数据结构。
23、什么是聚簇索引?
聚簇索引是一种数据库索引方式,它将数据行与索引存储在一起,使得索引的叶子节点包含了实际的数据行。
一、聚簇索引
- 数据存储有序
聚簇索引按照索引字段的值对数据进行物理排序存储。这使得在基于聚簇索引进行范围查询和排序操作时非常高效,因为数据在磁盘上是连续存储的。 - 主键通常是聚簇索引
在许多数据库中,表的主键默认会创建聚簇索引。这是因为主键通常用于唯一标识表中的每一行数据,并且在大多数情况下,基于主键的查询是最频繁的。 - 插入和更新的成本
由于聚簇索引的数据是按照特定顺序存储的,当插入或更新数据时,可能需要移动大量的数据行以保持数据的有序性。这会导致插入和更新操作的成本相对较高。
二、非聚簇索引
- 索引与数据分离
非聚簇索引的叶子节点不包含实际的数据行,而是存储了指向数据行的指针。这使得非聚簇索引的结构相对较小,占用的存储空间较少。 - 多个非聚簇索引
一个表可以有多个非聚簇索引,每个非聚簇索引可以根据不同的字段建立。这使得可以根据不同的查询需求选择合适的索引,提高查询性能。 - 插入和更新的成本较低
由于非聚簇索引与数据是分离的,插入和更新数据时只需要更新索引中的指针,而不需要移动实际的数据行。这使得插入和更新操作的成本相对较低。
24、何时使用聚簇索引与非聚簇索引
- 使用聚簇索引的情况
频繁进行范围查询和排序操作的字段。例如,按照时间顺序查询日志记录,或者按照价格范围查询商品信息。
主键字段通常是建立聚簇索引的好选择,因为主键通常用于唯一标识数据行,并且基于主键的查询非常频繁。
当表中的数据相对稳定,插入和更新操作较少时,聚簇索引可以提供更好的性能。 - 使用非聚簇索引的情况
经常进行等值查询的字段,例如根据用户 ID 查询用户信息。
当表中的数据经常发生变化,插入和更新操作频繁时,非聚簇索引可以减少对数据的移动,提高性能。
需要多个索引来满足不同查询需求的情况。例如,一个表既有按照姓名查询的需求,又有按照年龄查询的需求,可以分别建立非聚簇索引。
总之,聚簇索引和非聚簇索引在数据存储方式、性能特点和适用场景等方面都有所不同。在设计数据库时,需要根据具体的查询需求和数据特点来选择合适的索引类型,以提高数据库的性能。
25、联合索引是什么?为什么需要注意联合索引中的顺序?
MySQL可以使用多个字段同时建立一个索引,叫做联合索引。在联合索引中,如果想要命中索引,需要按照建立索引时的字段顺序挨个使用,否则无法命中索引。
具体原因为:
-
提高查询性能
当查询条件涉及多个字段时,如果这些字段有联合索引,数据库可以快速定位到满足条件的数据行,而不必进行全表扫描或多次单字段索引的查找。 -
减少索引数量
可以用一个联合索引替代多个单字段索引,减少索引占用的存储空间,并且在一定程度上提高数据的插入和更新性能。
二、联合索引中顺序的重要性
- 索引的最左前缀原则
数据库在使用联合索引进行查询时,会遵循最左前缀原则。即查询条件中必须包含联合索引的最左侧字段,并且按照索引定义的字段顺序依次匹配,才能使用该联合索引。
例如,有一个联合索引由字段 A、B、C 组成,只有查询条件中包含字段 A,或者同时包含字段 A 和 B,或者同时包含字段 A、B 和 C 时,才能使用这个联合索引。如果查询条件只包含字段 B 或 C,将无法使用该联合索引。 - 影响查询性能和索引选择
联合索引中字段的顺序会影响数据库对索引的选择和查询性能。如果查询条件中最频繁使用的字段放在联合索引的最左侧,数据库更有可能使用该联合索引,从而提高查询性能。
比如,在一个商品表中,如果经常根据商品类别和价格进行查询,建立联合索引时应该将商品类别字段放在前面,价格字段放在后面。这样,当查询条件中包含商品类别时,数据库更有可能使用这个联合索引。
事务
26、 什么是数据库事务
事务是一个不可分割的数据库操作序列,也是数据库并发控制的基本单位,其执行的结果必须使数据库从一种一致性状态变到另一种一致性状态。事务是逻辑上的一组操作,要么都执行,要么都不执行。
27、事物的四大特性(ACID)
- 原子性: 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
- 一致性: 执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相同的;
- 隔离性: 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
- 持久性: 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
28、什么是脏读?幻读?不可重复读?
- 脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。
- 不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。
- 幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。
29、什么是事务的隔离级别?MySQL的默认隔离级别是什么?
为了达到事务的四大特性,数据库定义了4种不同的事务隔离级别,由低到高依次为Read uncommitted、Read committed、Repeatable read、Serializable,这四个级别可以逐个解决脏读、不可重复读、幻读这几类问题。
- EAD-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
- READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。
- REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
- SERIALIZABLE(可串行化): 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。
Mysql 默认采用的 REPEATABLE_READ隔离级别 Oracle 默认采用的 READ_COMMITTED隔离级别
30、按照锁的粒度分数据库锁有哪些
在关系型数据库中,可以按照锁的粒度把数据库锁分为行级锁(INNODB引擎)、表级锁(MYISAM引擎)和页级锁(BDB引擎 )。
MyISAM和InnoDB存储引擎使用的锁:
- MyISAM采用表级锁(table-level locking)。
- InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁
行级锁,表级锁和页级锁对比
- 行级锁 行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小,但加锁的开销也最大。行级锁分为共享锁 和 排他锁。
特点:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
- 表级锁 表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持。最常使用的MYISAM与INNODB都支持表级锁定。表级锁定分为表共享读锁(共享锁)与表独占写锁(排他锁)。
特点:开销小,加锁快;不会出现死锁;锁定粒度大,发出锁冲突的概率最高,并发度最低。
- 页级锁 页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。
特点:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般
31、从锁的类别上分MySQL都有哪些锁呢
从锁的类别上来讲,有共享锁和排他锁。
-
共享锁: 又叫做读锁。 当用户要进行数据的读取时,对数据加上共享锁。共享锁可以同时加上多个。
-
排他锁: 又叫做写锁。 当用户要进行数据的写入时,对数据加上排他锁。排他锁只可以加一个,他和其他的排他锁,共享锁都相斥。
32、数据库的乐观锁和悲观锁是什么?怎么实现的?
-
悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。在查询完数据的时候就把事务锁起来,直到提交事务。实现方式:使用数据库中的锁机制
-
乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。在修改数据的时候把事务锁起来,通过version的方式来进行锁定。实现方式:乐一般会使用版本号机制或CAS算法实现。
两种锁的使用场景
从上面对两种锁的介绍,我们知道两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。
但如果是多写的情况,一般会经常产生冲突,这就会导致上层应用会不断的进行retry,这样反倒是降低了性能,所以一般多写的场景下用悲观锁就比较合适。
sql优化
1、如何定位SQL语句的性能问题
- 观察执行时间
使用数据库的性能监控工具或查询执行时间统计功能,记录 SQL 语句的执行时间。如果执行时间明显过长,就可能存在性能问题。
对于一些数据库管理系统,可以在 SQL 语句前加上特定的关键字(如在 MySQL 中使用 EXPLAIN)来查看语句的执行计划和预估执行时间。 - 分析资源使用情况
检查数据库服务器的 CPU、内存、磁盘 I/O 等资源的使用情况。如果某个资源使用率过高,可能与特定的 SQL 查询有关。
数据库管理系统通常提供监控工具,可以查看当前正在执行的查询以及它们的资源使用情况。 - 查看日志文件
数据库的日志文件可能会记录查询的执行情况、错误信息和性能相关的事件。检查日志文件可以发现潜在的性能问题和错误。
使用数据库性能分析工具
有许多第三方工具可以分析数据库的性能,提供详细的查询执行统计信息、索引使用情况和性能建议。
2、如何优化SQL语句的性能问题
- 优化查询结构
避免使用复杂的子查询和嵌套查询,可以考虑使用连接(JOIN)来代替。
减少不必要的列选择,只选择需要的列,避免使用 SELECT *。
对于复杂的逻辑,可以考虑将其拆分为多个简单的查询,然后在应用程序层面进行组合。 - 合理使用索引
分析查询中涉及的列,为经常用于查询条件、连接条件和排序的列创建合适的索引。
避免创建过多的索引,因为索引会占用额外的存储空间,并且在数据插入、更新和删除时会增加维护成本。
定期检查和优化索引,删除不再使用的索引。 - 优化数据库设计
规范化数据库设计可以减少数据冗余,但过度规范化可能会导致复杂的查询。在性能要求较高的情况下,可以适当进行反规范化设计。
合理划分表,将大表拆分为小表,根据业务需求进行垂直或水平分割。 - 调整数据库参数
不同的数据库管理系统有许多可调整的参数,如缓存大小、连接数、排序缓冲区等。根据服务器的硬件资源和应用程序的需求,调整这些参数可以提高性能。
但在调整参数时要谨慎,避免过度调整导致其他问题。 - 优化数据库服务器配置
确保数据库服务器有足够的内存、CPU 和磁盘空间。
调整操作系统的参数,如文件系统缓存、网络设置等,以提高数据库的性能。 - 定期维护数据库
定期进行数据库备份、清理无用数据、重建索引和优化表结构等维护操作,可以提高数据库的性能和稳定性。 - 优化应用程序代码
在应用程序层面,减少对数据库的频繁访问,避免不必要的查询和数据加载。
合理使用数据库连接池,避免频繁创建和关闭连接。
通过以上方法,可以有效地定位和优化 SQL 语句的性能问题,提高数据库的性能和应用程序的响应速度。
3、什么是执行计划
执行计划(Execution Plan)也称为查询计划,是数据库管理系统(DBMS)为了执行特定的 SQL 查询语句而生成的一系列步骤的描述。不同的数据库管理系统提供的执行计划的详细程度和格式可能会有所不同,但它们的目的都是为了帮助用户了解查询的执行方式,以便进行性能优化和故障排除。
执行计划包含的信息 id 有一组数字组成。表示一个查询中各个子查询的执行顺序;
- id相同执行顺序由上至下。
- id不同,id值越大优先级越高,越先被执行。
- id为null时表示一个结果集,不需要使用它查询,常出现在包含union等查询语句中。
select_type 每个子查询的查询类型,一些常见的查询类型。
table 查询的数据表,当从衍生表中查数据时会显示 x 表示对应的执行计划id partitions 表分区、表创建的时候可以指定通过那个列进行表分区。 举个例子:
create table tmp (
id int unsigned not null AUTO_INCREMENT,
name varchar(255),
PRIMARY KEY (id)
) engine = innodb
partition by key (id) partitions 5;
type(非常重要,可以看到有没有走索引) 访问类型
- ALL 扫描全表数据
- index 遍历索引
- range 索引范围查找
- index_subquery 在子查询中使用 ref
- unique_subquery 在子查询中使用 eq_ref
- ref_or_null 对Null进行索引的优化的 ref
- fulltext 使用全文索引
- ref 使用非唯一索引查找数据
- eq_ref 在join查询中使用PRIMARY KEYorUNIQUE NOT NULL索引关联。
- possible_keys 可能使用的索引,注意不一定会使用。查询涉及到的字段上若存在索引,则该索引将被列出来。当该列为 NULL时就要考虑当前的SQL是否需要优化了。
key 显示MySQL在查询中实际使用的索引,若没有使用索引,显示为NULL。
**TIPS:**查询中若使用了覆盖索引(覆盖索引:索引的数据覆盖了需要查询的所有数据),则该索引仅出现在key列表中
key_length 索引长度
ref 表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值
rows 返回估算的结果集数目,并不是一个准确的值。
extra 的信息非常丰富,常见的有:
- Using index 使用覆盖索引
- Using where 使用了用where子句来过滤结果集
- Using filesort 使用文件排序,使用非索引列进行排序时出现,非常消耗性能,尽量优化。
- Using temporary 使用了临时表 sql优化的目标可以参考阿里开发手册
【推荐】SQL性能优化的目标:至少要达到 range 级别,要求是ref级别,如果可以是consts最好。
说明:
1) consts 单表中最多只有一个匹配行(主键或者唯一索引),在优化阶段即可读取到数据。
2) ref 指的是使用普通的索引(normal index)。
3) range 对索引进行范围检索。
反例:explain表的结果,type=index,索引物理文件全扫描,速度非常慢,这个index级别比较range还低,与全表扫描是小巫见大巫。
4、SQL的生命周期
-
应用服务器与数据库服务器建立一个连接
-
数据库进程拿到请求sql
-
解析并生成执行计划,执行
-
读取数据到内存并进行逻辑处理
-
通过步骤一的连接,发送结果到客户端
-
关掉连接,释放资源
5、大表数据查询,怎么优化
当查询大表数据时,可以考虑以下方法进行优化:
一、数据库设计优化
-
合理创建索引
- 分析查询中经常使用的条件字段、连接字段和排序字段,为这些字段创建合适的索引。但要注意避免创建过多索引,因为索引会占用额外的存储空间,并且在数据插入、更新和删除时会增加维护成本。
- 对于复合索引,要根据查询的条件顺序合理安排索引字段的顺序。
-
表分区
- 根据特定的规则将大表分割成多个小的分区,可以提高查询性能。例如,可以按照时间、范围或哈希值进行分区。
- 分区后,数据库可以只扫描特定的分区,而不是整个表,从而减少了数据读取量。
二、查询语句优化
-
避免全表扫描
- 确保查询语句中使用了合适的索引,避免使用
SELECT *
语句,只选择需要的字段。 - 尽量减少不必要的子查询和复杂的连接操作。
- 确保查询语句中使用了合适的索引,避免使用
-
分页查询优化
- 对于大量数据的分页查询,可以使用数据库提供的优化技术,如 MySQL 的
LIMIT
和OFFSET
结合索引使用,或者使用数据库的特定分页函数。 - 避免在大结果集上进行深度分页,因为这可能会导致性能急剧下降。
- 对于大量数据的分页查询,可以使用数据库提供的优化技术,如 MySQL 的
-
优化查询条件
- 使用合适的查询条件,避免使用模糊查询(如
LIKE '%value%'
),因为这通常会导致全表扫描。如果可能,使用前缀模糊查询(如LIKE 'value%'
),这样可以利用索引。 - 对于范围查询,确保索引对查询条件有效。
- 使用合适的查询条件,避免使用模糊查询(如
三、数据库配置优化
-
调整内存参数
- 增加数据库缓存的大小,如 MySQL 的
innodb_buffer_pool_size
,以提高数据的缓存命中率,减少磁盘 I/O。
- 增加数据库缓存的大小,如 MySQL 的
-
优化连接参数
- 根据服务器的硬件资源和并发连接数,调整数据库的连接参数,如最大连接数、连接超时时间等。
四、硬件和架构优化
-
增加硬件资源
- 如果可能,增加服务器的内存、CPU 和磁盘性能。例如,使用更快的磁盘(如 SSD)可以提高数据的读取速度。
-
数据库集群和分布式架构
- 考虑使用数据库集群或分布式数据库架构,将数据分布在多个节点上,并行处理查询请求,提高查询性能和可扩展性。
-
缓存机制
- 在应用层使用缓存(如 Redis)来缓存经常访问的数据,减少对数据库的查询次数。
6、超大分页怎么处理
处理超大分页问题可以从以下几个方面入手:
一、数据库层面优化
-
合理利用索引
- 如果分页查询是基于某个有序字段(比如自增主键、时间戳等)进行的,可以利用索引来快速定位数据范围。例如,在 MySQL 中,如果有一个自增主键
id
,分页查询可以使用WHERE id > [起始值] LIMIT [每页条数]
的方式,这样数据库可以通过索引快速定位到起始值之后的记录。 - 对于复合索引,确保索引的顺序与查询条件的顺序一致,以提高索引的使用效率。
- 如果分页查询是基于某个有序字段(比如自增主键、时间戳等)进行的,可以利用索引来快速定位数据范围。例如,在 MySQL 中,如果有一个自增主键
-
避免使用
OFFSET
- 在处理超大分页时,使用
OFFSET
会导致数据库需要先查询出前面的大量数据,然后再丢弃,非常浪费资源。可以考虑使用基于游标的方式或者通过记录上一页的最后一个值来进行分页查询。 - 例如,使用上一页最后一个记录的
id
值作为下一页查询的起始条件,而不是使用OFFSET
。
- 在处理超大分页时,使用
二、应用层面优化
-
限制分页大小
- 可以在应用程序中设置一个合理的最大分页大小,避免用户请求过大的分页数据。例如,限制每页最多显示 1000 条记录,如果用户需要查看更多数据,可以通过其他方式(如搜索、筛选等)缩小数据范围。
-
缓存分页结果
- 对于一些频繁访问的分页数据,可以在应用层进行缓存。当用户请求相同的分页时,直接从缓存中返回结果,而不需要再次查询数据库。
- 可以使用缓存服务器(如 Redis)来存储分页结果,设置合理的缓存过期时间,以保证数据的新鲜度。
三、数据库架构优化
-
数据库分区
- 如果数据库表非常大,可以考虑对表进行分区。根据一定的规则(如时间、范围等)将表分成多个分区,这样在进行分页查询时,可以只查询特定的分区,减少数据扫描范围。
-
数据库集群和分布式架构
- 使用数据库集群或分布式数据库架构可以将数据分布在多个节点上,并行处理查询请求。对于超大分页查询,可以将查询任务分发到多个节点上进行处理,然后在应用层进行结果合并。
四、用户体验优化
-
提供渐进式加载
- 对于大数据集,可以采用渐进式加载的方式,即先加载一部分数据,当用户滚动页面或触发特定操作时,再加载更多数据。这样可以减少初始加载时间,提高用户体验。
-
提供搜索和筛选功能
- 鼓励用户使用搜索和筛选功能来缩小数据范围,而不是直接请求超大分页。这样可以减少数据库的查询压力,提高查询性能。
7、慢查询日志
慢查询日志是数据库用来记录执行时间超过特定阈值的 SQL 查询语句的日志。以下是关于慢查询日志的详细介绍:
一、作用
-
性能分析
- 通过分析慢查询日志,可以找出执行时间较长的 SQL 语句,从而确定数据库性能瓶颈所在。这有助于数据库管理员和开发人员针对性地进行优化,提高数据库的整体性能。
- 可以了解哪些查询是频繁出现的慢查询,以便重点优化这些查询。
-
故障排查
- 当数据库出现性能问题时,慢查询日志可以提供线索,帮助确定问题是否由特定的 SQL 查询引起。
- 对于突然出现的性能下降,可以通过对比不同时间段的慢查询日志,找出可能导致问题的查询语句变化。
二、开启和配置
不同的数据库系统开启和配置慢查询日志的方式略有不同。以 MySQL 为例:
-
开启慢查询日志
- 在 MySQL 的配置文件(通常是
my.cnf
或my.ini
)中添加以下参数:slow_query_log = 1
- 重启 MySQL 服务使配置生效。
- 在 MySQL 的配置文件(通常是
-
设置慢查询时间阈值
- 可以通过
long_query_time
参数设置慢查询的时间阈值,单位为秒。例如:long_query_time = 2
- 这表示执行时间超过 2 秒的查询将被记录到慢查询日志中。
- 可以通过
三、日志内容和格式
-
日志内容
- 通常包括执行的 SQL 语句、执行时间、查询锁等待时间、扫描的行数等信息。
- 例如在 MySQL 中,慢查询日志可能包含以下信息:
# Time: 2024-09-23T12:34:56 # User@Host: user[user] @ localhost [127.0.0.1] # Query_time: 2.500000 Lock_time: 0.000000 Rows_sent: 100 Rows_examined: 10000 SELECT * FROM large_table WHERE column_name = 'value';
-
日志格式
- 不同的数据库系统可能有不同的日志格式,但一般都包含查询的关键信息,以便进行分析。
四、分析慢查询日志
-
使用数据库自带的工具
- 一些数据库系统提供了工具来分析慢查询日志,例如 MySQL 的
mysqldumpslow
工具,可以统计慢查询的出现次数、平均执行时间等信息。
- 一些数据库系统提供了工具来分析慢查询日志,例如 MySQL 的
-
使用第三方工具
- 有许多第三方工具可以对慢查询日志进行更详细的分析,如 pt-query-digest。这些工具可以生成详细的报告,包括查询的执行计划、索引使用情况等,帮助更好地理解和优化慢查询。
五、注意事项
-
日志文件大小管理
- 慢查询日志可能会随着时间增长而变得很大,需要定期清理或归档旧的日志文件,以避免占用过多磁盘空间。
- 可以设置日志文件的最大大小,当达到这个大小后,自动进行轮转或清理。
-
对性能的影响
- 开启慢查询日志会对数据库性能产生一定的影响,因为数据库需要额外的资源来记录慢查询。在生产环境中,需要权衡性能和分析需求,合理设置慢查询日志的参数。
8、MySQL数据库cpu飙升到500%的话他怎么处理
当 MySQL 数据库 CPU 飙升到 500%时,可以按照以下步骤进行处理:
一、观察和记录
- 记录当前时间和问题现象,包括 CPU 使用率突然飙升的具体数值。
- 查看数据库的错误日志和慢查询日志,看是否有异常的错误信息或慢查询记录。
二、使用监控工具
- 利用数据库监控工具(如 MySQL Enterprise Monitor、Percona Monitoring and Management 等)或操作系统的监控工具(如 top、htop 等)来确定哪些进程或查询导致了高 CPU 使用率。
- 观察正在执行的 SQL 语句、连接数、锁等待等信息。
三、应急处理
- 考虑暂时停止一些非关键的应用程序对数据库的访问,以减轻数据库的负载,观察 CPU 使用率是否下降。
- 如果可能,重启 MySQL 服务。这虽然是一种临时解决方案,但可以快速恢复系统的可用性,同时也可能清除一些导致问题的临时状态。
四、分析问题原因
-
慢查询
- 检查慢查询日志,找出执行时间较长的查询语句。使用
EXPLAIN
命令分析这些查询的执行计划,看是否存在全表扫描、缺少索引等问题。 - 对慢查询进行优化,如添加合适的索引、优化查询语句结构等。
- 检查慢查询日志,找出执行时间较长的查询语句。使用
-
高并发连接
- 检查当前的连接数,看是否存在过多的连接。如果是,可以考虑调整数据库的最大连接数参数(如
max_connections
)。 - 分析连接的来源,看是否存在某些应用程序创建了过多的连接而没有及时释放。
- 检查当前的连接数,看是否存在过多的连接。如果是,可以考虑调整数据库的最大连接数参数(如
-
锁等待
- 使用数据库监控工具或查询系统表(如
information_schema.INNODB_LOCKS
、information_schema.INNODB_LOCK_WAITS
)来检查是否存在锁等待的情况。 - 分析锁等待的原因,可能是由于事务没有正确提交或回滚、长时间运行的查询持有了锁等。对有问题的事务进行处理,或者优化查询以减少锁的持有时间。
- 使用数据库监控工具或查询系统表(如
-
数据库参数设置不合理
- 检查数据库的参数设置,如缓存大小(
innodb_buffer_pool_size
)、排序缓冲区大小(sort_buffer_size
)等。不合理的参数设置可能导致性能问题。 - 根据服务器的硬件资源和数据库的负载情况,调整参数以优化性能。
- 检查数据库的参数设置,如缓存大小(
-
硬件问题
- 如果以上方法都没有解决问题,可能需要考虑硬件问题。检查服务器的 CPU、内存、磁盘 I/O 等资源的使用情况,看是否存在硬件故障或资源瓶颈。
五、预防措施
- 定期进行数据库性能优化,包括索引优化、查询优化、数据库参数调整等。
- 建立数据库监控机制,及时发现和处理性能问题。
- 对应用程序进行优化,避免编写低效的 SQL 查询和不合理的数据库访问逻辑。
- 定期备份数据库,以便在出现严重问题时能够快速恢复。
9、长难的查询语句怎么优化
以下是一些优化长难查询语句的方法:
一、分析查询需求
-
理解业务目的:
- 明确查询的具体业务需求,确定需要获取哪些信息,避免不必要的查询内容。
- 例如,如果只需要查询特定时间段内的销售数据,就不要查询所有时间的销售数据。
-
检查数据来源:
- 确定查询的数据表是否正确,是否有更合适的数据源可以使用。
- 有时候,从经过预处理的汇总表查询可能比从原始数据表查询更高效。
二、简化查询语句结构
-
分解复杂查询:
- 将复杂的查询拆分成多个简单的子查询,逐步构建结果。这样可以更容易理解和调试查询,也有助于优化每个子查询。
- 例如,先查询出满足特定条件的中间结果集,然后再对中间结果集进行进一步的筛选和聚合。
-
使用临时表或视图:
- 如果查询中包含多个重复的子查询或复杂的计算,可以考虑创建临时表或视图来存储中间结果,然后在主查询中引用这些临时表或视图。
- 这样可以避免重复计算,提高查询性能。
-
避免不必要的函数调用:
- 减少在查询条件中使用复杂的函数调用,特别是那些对大量数据进行处理的函数。
- 如果可能,尽量在数据加载或预处理阶段进行数据转换和计算,而不是在查询时进行。
三、优化查询条件
-
使用合适的索引:
- 确保在查询中经常使用的列上创建了合适的索引。索引可以大大提高查询的速度,但过多或不合适的索引也会影响数据库的性能。
- 分析查询的执行计划,确定哪些列需要索引,以及索引的类型(如 B 树索引、哈希索引等)。
-
优化条件表达式:
- 尽量使用简单的条件表达式,避免复杂的逻辑运算和函数调用。
- 例如,使用“=”、“>”、“<”等比较运算符代替复杂的函数来进行条件判断。
-
限制查询结果集:
- 使用“LIMIT”或“TOP”等语句限制查询返回的结果集大小,避免返回过多不必要的数据。
- 如果只需要查询前 N 条记录,可以使用“ORDER BY”和“LIMIT”组合来实现。
四、数据库参数调整
-
调整内存设置:
- 根据数据库服务器的硬件资源,合理调整数据库的内存参数,如缓冲池大小、排序缓冲区大小等。
- 增加内存可以减少磁盘 I/O 操作,提高查询性能。
-
优化连接参数:
- 对于多表连接的查询,调整连接参数,如连接算法、连接顺序等,可以提高连接的效率。
- 分析查询的执行计划,确定是否存在连接性能问题,并进行相应的调整。
五、定期维护数据库
-
清理数据:
- 定期清理不再需要的数据,减少数据库的大小,提高查询性能。
- 可以删除过期的记录、备份数据等。
-
优化数据库结构:
- 随着时间的推移,数据库结构可能会变得不合理,影响查询性能。定期对数据库结构进行优化,如添加或删除索引、调整表结构等。
-
执行数据库维护任务:
- 定期执行数据库的维护任务,如索引重建、统计信息更新等。这些任务可以帮助数据库优化查询计划,提高查询性能。
总之,优化长难查询语句需要综合考虑多个方面,包括查询需求、语句结构、查询条件、数据库参数和数据库维护等。通过不断地分析和优化,可以提高查询的性能和效率。
10、mysql如何快速插入千万级大数据
在 MySQL 中快速插入千万级大数据可以从以下几个方面进行优化:
一、关闭自动提交
在插入数据之前,可以先关闭自动提交,将多个插入操作作为一个事务处理,这样可以减少事务提交的次数,提高插入速度。
START TRANSACTION;
-- 插入数据的 SQL 语句
COMMIT;
二、调整存储引擎参数
-
如果使用 InnoDB 存储引擎,可以调整以下参数:
innodb_buffer_pool_size
:增加缓冲池大小,提高缓存命中率,减少磁盘 I/O。innodb_flush_log_at_trx_commit
:可以设置为 0 或 2,减少日志刷新的频率,提高写入性能,但会降低数据的持久性。
-
如果使用 MyISAM 存储引擎,可以调整以下参数:
key_buffer_size
:增加索引缓冲区大小,提高索引写入速度。
三、批量插入
使用批量插入语句可以减少数据库连接和 SQL 解析的开销,提高插入速度。例如:
INSERT INTO table_name (column1, column2, column3) VALUES
(value1_1, value1_2, value1_3),
(value2_1, value2_2, value2_3),
(value3_1, value3_2, value3_3);
也可以使用存储过程来实现批量插入。
四、禁用索引和外键约束
在插入数据时,可以先禁用索引和外键约束,插入完成后再重新启用。这样可以避免在插入过程中维护索引和外键约束,提高插入速度。
-- 禁用索引
ALTER TABLE table_name DISABLE KEYS;
-- 插入数据的 SQL 语句
-- 启用索引
ALTER TABLE table_name ENABLE KEYS;
五、使用 LOAD DATA INFILE 语句
如果数据可以以文本文件的形式提供,可以使用 LOAD DATA INFILE
语句来快速导入数据。这个语句可以直接从文件中读取数据并插入到表中,速度非常快。
LOAD DATA INFILE '/path/to/file.csv' INTO TABLE table_name
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n';
六、硬件优化
- 增加内存:更多的内存可以提高数据库的缓存能力,减少磁盘 I/O。
- 使用固态硬盘(SSD):SSD 具有更快的读写速度,可以提高数据库的性能。
七、并行插入
如果数据库服务器有多个 CPU 核心,可以考虑使用并行插入的方式,将数据分成多个部分,同时在不同的线程或进程中进行插入。但这需要根据具体的数据库架构和业务需求进行实现。