Mysql - 索引

news2024/11/15 4:27:42

目录

一、存储引擎

二、索引

索引结构

索引分类

 索引语法

 联合索引

前缀索引

索引使用规则

最左前缀法则

范围查询使索引失效 

字段做运算操作索引失效

字符串字段不加单引号索引失效

 字段做前模糊查询索引失效

or连接条件索引失效

数据发布情况索引失效

指定使用索引

三、帮助 SQL优化的工具

慢查询日志记录

 profiles

explain

四、SQL优化

为什么不要使用select *

插入优化 insert

主键优化

排序优化 order by

 分组优化group by

limit优化

count优化

update优化


一、存储引擎

MySQL体系结构:

查询当前数据库支持的存储引擎:

show engines ;

InnoDB是默认的存储引擎,也是最常用的,广泛应用于各种需要高并发和高可靠性的应用场景(支持事务、行级锁和外键

InnoDB引擎的数据文件:

xxx.ibd:xxx代表的是表名,innoDB引擎的每张表都会对应这样一个表空间文件,存储该表的表结构、数据和索引。

  • 表空间 : InnoDB存储引擎逻辑结构的最高层,ibd文件其实就是表空间文件,在表空间中可以 包含多个Segment段。
  • 段 : 表空间是由各个段组成的, 常见的段有数据段、索引段、回滚段等。InnoDB中对于段的管 理,都是引擎自身完成,不需要人为对其控制,一个段中包含多个区。
  • 区 : 区是表空间的单元结构,每个区的大小为1M。 默认情况下, InnoDB存储引擎页大小为 16K, 即一个区中一共有64个连续的页。
  • 页 : 页是组成区的最小单元,页也是InnoDB 存储引擎磁盘管理的最小单元,每个页的大小默 认为 16KB。为了保证页的连续性,InnoDB 存储引擎每次从磁盘申请 4-5 个区。
  • 行 : InnoDB 存储引擎是面向行的,也就是说数据是按行进行存放的,在每一行中除了定义表时 所指定的字段以外

创建表时,没有指定存储引擎,默认是InnoDB存储引擎。查看指定表使用的存储引擎等信息:

show create table emp;

 MyISAM是MySQL早期的默认存储引擎。(不支持事务,不支持外键 支持表锁,不支持行锁 访问速度快)

储存的文件 xxx.sdi:存储表结构信息 xxx.MYD: 存储数据 xxx.MYI: 存储索引

Memory引擎的表数据时存储在内存中的,由于受到硬件问题或断电问题的影响,只能将这些表作为临时表或缓存使用

在选择存储引擎时,应该根据应用系统的特点选择合适的存储引擎。对于复杂的应用系统,还可以根据 实际情况选择多种存储引擎进行组合。

  • InnoDB: 是Mysql的默认存储引擎,支持事务、外键。如果应用对事务的完整性有比较高的要 求,在并发条件下要求数据的一致性,数据操作除了插入和查询之外,还包含很多的更新、删除操 作,那么InnoDB存储引擎是比较合适的选择。
  • MyISAM : 如果应用是以读操作和插入操作为主,只有很少的更新和删除操作,并且对事务的完 整性、并发性要求不是很高,那么选择这个存储引擎是非常合适的。
  • MEMORY:将所有数据保存在内存中,访问速度快,通常用于临时表及缓存。MEMORY的缺陷就是 对表的大小有限制,太大的表无法缓存在内存中,而且无法保障数据的安全性。

二、索引

索引是一种用于提高数据库查询效率的数据结构。通过为表中的数据创建索引,即利用数据结构为数据创建一种映射关系,可以显著减少查询所需的时间,从而提高数据库的整体性能

索引结构

MySQL的索引是在存储引擎层实现的,不同的存储引擎有不同的索引结构,索引主要有以下几种:

索引结构描述
B+Tree索引最常见的索引类型,大部分引擎都支持 B+ 树索引
Hash索引底层数据结构是用哈希表实现的, 只有精确匹配索引列的查询才有效, 不 支持范围查询
R-tree(空间索 引)空间索引是MyISAM引擎的一个特殊索引类型,主要用于地理空间数据类 型,通常使用较少
Full-text(全文 索引)是一种通过建立倒排索引,快速匹配文档的方式。类似于Elasticsearch

B Tree的结构:

对于二叉树而言,最多只能有两个孩子节点,(度数最多为 2),但B树可以有多个孩子节点

最多有 n 个节点,那么就称为 n 阶B树,以 5 阶B树为例:

那这个B树每个节点最多存储4个key,5 个指针,即每个节点最多存储4个值和指向孩子节点的5个指针

 查数据时,与二叉搜索树类似,比插入值大的走右边,小的走左边,以下5阶B树插入数值19为例,其结构示意图:

 key的数量为5超过了4,需要分裂,中间元素上移。

B+Tree索引

B+Tree是B-Tree的变种,在分裂上移时,只是将key值赋值一份上移,值仍然存储在最下面的叶子节点上,也就是说,数据只存储在叶子节点 上,其它节点储存的是索引(key),在Mysql的B+Tree索引中,所有的叶子节点会形成双向链表,这样就可以做范围查询和排序等操作

 

为什么InnoDB存储引擎选择使用B+tree索引结构?

A. 相对于二叉树,层级更少,搜索效率高;

B. 对于B-tree,无论是叶子节点还是非叶子节点,都会保存数据,这样导致一页中存储 的键值减少,指针跟着减少,要同样保存大量数据,只能增加树的高度,导致性能降低;

C. 相对Hash索引,B+tree支持范围匹配及排序操作;

MySQL中除了支持B+Tree索引,还支持一种索引类型---Hash索引。

Hash索引

将数据库中每一行数据有对应的哈希值,当我们对name字段添加索引时,就会为name所有值生成对应的hash值,映射到对应的槽位上,然后将name值和每一行得hash值存储在 hash表中,如果两个(或多个)键值,映射到一个相同的槽位上,他们就产生了hash冲突(也称为hash碰撞),可以通过链表来解决,也就是相同hash值得使用链表储存。

  • Hash索引只能用于对等比较(=,in),不支持范围查询(between,>,< ,...)
  • 无法利用索引完成排序操作
  • 查询效率高,通常(不存在hash冲突的情况)只需要一次检索就可以了,效率通常要高于B+tree索 引

索引分类

在MySQL数据库,将索引的具体类型主要分为以下几类:

主键索引(PRIMARY)、唯一索引(UNIQUE)、常规索引、全文索引

 其中主键索引只能有一个其它可以有多个

主键索引(PRIMARY)、唯一索引(UNIQUE)在建表时指定主键或唯一约束时会自动创建索引

常规索引为对特定数据创建索引

聚集索引、二级索引

在InnoDB存储引擎中,根据索引的存储形式,又可以分为以下两种:

  1. 聚集索引(Clustered Index):将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据(必须有,而且只 有一个)
  2. 二级索引(Secondary Index):(辅助索引)将数据与索引分开存储,索引结构的叶子节点存放的值是对应的主键索引列的值

聚集索引选取规则:

如果存在主键,主键索引就是聚集索引。 如果不存在主键,将使用第一个唯一(UNIQUE)索引作为聚集索引。 如果表没有主键,或没有合适的唯一索引,则InnoDB会自动生成一个rowid作为隐藏的聚集索 引。

在查询二级索引中的数据时,会根据创建的索引去查询对应的主键,再根据主键去查询对应的整行数据,例如以下SQL:

select * from emp where name='Arm' ;

查询过程是:实现在二级索引中查询对应的主键id,再根据主键id去聚集索引去查询对应的行数据

而下面的SQL则是直接从聚集索引中查询整条数据,效率会更高些:

select * from emp where id= 10 ;

回表查询: 这种先到二级索引中查找数据,找到主键值,然后再到聚集索引中根据主键值,获取 数据的方式,就称之为回表查询。

 假设: 一行数据大小为1k,一页中可以存储16行这样的数据,即一页(一个叶子节点)可以存放16K的数据

InnoDB的指针占用6个字节的空间,主键假使为bigint,占用字节数为8。一个节点中指针数量永远比主键数量多一,所以:

高度为2: (n + 1) * 6 + n * 8 = 16*1024 , 算出n约为 1170,即指针有1171个,所以叶子节点有1171个,又每个叶子节点可以存储16行数据,所以:

1171 * 16 = 18736

即高度为2的树可以存储 18000 多条记录。

高度为3: 1171 * 1171 * 16 = 21939856,因为1170个节点中,每个节点又可以存储1171个子节点,也就是说,如果树的高度为3,则可以存储 2200w 左右的记录。

 阿里巴巴 Java 开发手册V1.2中:

14. 【推荐】单表行数超过500万行或者单表容量超过2GB,才推荐进行分库分表。 说明:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表。

 索引语法

#查询索引
show index from tb_user;
#创建唯一索引 
create unique index idx_user_phone on tb_user(phone);
#创建单列索引
create index idx_email on tb_user(email);
#创建联合索引
create index idx_profession_age_status on tb_user (profession, age, status);

 联合索引

  (Composite Index)是由两个或多个列组成的索引。这种索引可以提高在多个列上执行查询时的性能。使用联合使用需要遵循最左前缀法则

单列索引和联合索引的选择:

当需要多个条件查询时,建议创建联合索引。例如:

select id,username,password from tb_user where phone = '18081404110' and username = '张三' ;

 若phone和username都是单列索引,只能走一个索引,所以需要去查询另一个字段,必然会走回表查询,只是可以对两字段建立联合索引避免。能使用联合索引尽量使用联合索引

前缀索引

前缀索引是指在针对某一字段创建索引时,字段类型为字符串(varchar,text,longtext等)(例如文章数据)时,该字段的内容可能会很庞大,建立的索引的体积就会非常大,浪费大量的磁盘IO, 影响查询效率。可以减少索引的存储空间和维护成本

 语法:通过截取该字段的前一部分来做为索引的值

#以email字段的前五个字符创建索引
create index idx_content on tb_user(content(5));

 前缀长度

可以根据不重复的索引值(基数)和数据表的记录总数的比值来确定(也称选择性), 比值越高则查询效率越高, 唯一索引的选择性是 1,这是最好的索引选择性,性能也是最好的。

 比值查询示例:

 select  count(distinct content) / count(*)   from  tb_user ;
 select  count(distinct substring(content,1,5)) / count(*)  from  tb_user ;

 查询流程:先通过前缀去索引中查,在通过id回表查询查出该字段的整体值,比对是否与给出条件符合。

索引设计原则

  • 1). 针对于数据量较大,且查询比较频繁的表建立索引。
  • 2). 针对于常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索 引。
  • 3). 尽量选择区分度高的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率越高。
  • 4). 如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引。
  • 5). 尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间, 避免回表,提高查询效率。
  • 6). 要控制索引的数量,索引并不是多多益善,索引越多,维护索引结构的代价也就越大,会影响增 删改的效率。
  • 7). 如果索引列不能存储NULL值,请在创建表时使用NOT NULL约束它。当优化器知道每列是否包含 NULL值时,它可以更好地确定哪个索引最有效地用于查询。

索引使用规则

最左前缀法则

在使用联合索引时应注意遵守的法则:

最左前缀法则:查询必须需包含的最左列, 并且不跳过索引中的列。如果跳跃某一列,索引将会部分失效(后面的字段索引失效)。

例如:以tb_user表的profession, age, status三个字段创建联合索引为例:

使用explain关键字可以显示 SQL 查询的执行计划,详细看【帮助 SQL优化的工具】

正常使用三字段时,走索引,三字段都走索引,索引长度为49:

当查询时没有最左列profession则不会使用索引查询:

当只使用profession字段,正常走索引,索引长度只有profession的长度47

当使用前两个字段时会走索引,profession和age两字段时索引长度为49

当中间age字段跳过,没有使用时,则此后面的字段status使用索引失效,索引长度只有profession的长度47

范围查询使索引失效 

若某字段出现范围查询小于(<)、大于(>)则该字段右侧的列索引会失效,例如age使用此范围查询时,status的索引会失效,但是使用小于等于(<=)、大于等于(>=)时不会失效

注意】这与我们写的SQL条件先后顺序无关,例如必须需包含的最左列,是指查询条件中有索引的最左列profession即可使索引失效。SQL中的条件书写顺序无需与索引顺序一致

字段做运算操作索引失效

当我们在使用某字段索引时,若对该索引做了运算,则会使索引失效。

例如:我们对手机号phone字段创建了索引,在使用时加了字符串截取的运算,查询手机号后四位为4110的用户信息,此时会使索引失效

select * from tb_user where substring(phone,7,4) = '4110';
字符串字段不加单引号索引失效

在字符串类型的字段做条件查询时,没加单引号,虽然能查出数据,但是不会走索引

select * from tb_user where substring(phone,7,4) = 4110 ;
 字段做前模糊查询索引失效

当对某字段做模糊查询时,只要%加在前面会使索引失效,比如:查询姓名以”三“结尾的用户信息

select * from tb_user where username like '%三' ;

 而以下形式就不会使索引失效:查询姓张的用户

select * from tb_user where username like '张%' ;
or连接条件索引失效

当使用or做连接条件查询时,需要or连接的条件的字段都要有索引才能使索引生效,有其中一个字段没有索引,索引都不会生效

例如:查询性别为男或则年龄为20的用户:若age有索引而gender没有索引,则索引失效

select * from tb_user where gender = '男' or age = 20 ;
数据发布情况索引失效

当我们在做查询时,绝大部分数据是满足我们的条件时,MySQL评估使用索引比全表更慢,则不使用索引,相反,Mysql评估走索引会更快才会走索引。

指定使用索引

当我们在做条件查询时,字段有多个索引时,可以指定Mysql使用哪个索引,有以下三种方式:

use 建议Mysql走指定索引,其中Mysql会做评估,有更快的索引时,不会走建议的索引

explain select * from tb_user use index(idx_profession) where profession = '英语' ;

ignore 忽略指定的索引:

explain select * from tb_user ignore index(idx_profession) where profession = '英语' ;

force 强制使用指定索引:

explain select * from tb_user force index(idx_profession) where profession = '英语' ;

三、帮助 SQL优化的工具

在MySQL中,SHOW GLOBAL STATUS 是一个非常有用的命令,它显示了服务器级别的状态变量。这些状态变量提供了关于服务器运行时的各种统计信息和性能指标。使用这个命令可以帮助你了解服务器的当前状态,诊断问题,或者优化数据库性能

使用like关键字进行过滤(Com后面7个 _ 模糊查询Com后7个字符的状态信息):

show global status like 'Com_______';

 索引主要是针对查询,当数据库查询占绝大部分比例时,可能需要考虑创建索引来优化数据库性能

慢查询日志记录

Mysql默认关闭,需要配置开启才能失效,可以通过这些记录去优化这些SQL

查询是否开启慢查询日志记录

show variables like 'slow_query_log' ;

 

 编辑my.cnf文件,末尾追加以下内容:

sudo vim /etc/mysql/my.cnf

 我的是Ubuntu系统,其它系统类似,windows中是my.ini

[mysqld]
#开启慢查询日志记录,当SQL执行时间超过指定时间时就会记录日志到/var/lib/mysql/localhost-slow.log
slow_query_log=1
#日志存放地址
slow_query_log_file = /var/log/mysql/mysql-slow.log
#指定时间
long_query_time=2

查询是否配置成功:

 profiles

使用profiles查询SQL执行时间等情况:

查看当前MySQL是否支持profile操作:

SELECT @@have_profiling ;

 开启profiling:

SET  profiling = 1;

 查询所有命令执行耗时和根据命令id查询耗时:

explain

        在MySQL中,EXPLAIN 是一个非常有用的命令,用于显示 SQL 查询的执行计划。执行计划是数据库如何执行查询的详细说明,包括它如何使用索引、表的连接顺序、预计需要扫描的行数等。通过分析执行计划,你可以优化查询性能,理解查询的工作原理。

 EXPLAIN 或者 DESC命令获取 MySQL 如何执行 SELECT 语句的信息,多条数据时包括在 SELECT 语句执行过程中表如何连接和连接的顺序

使用:直接在select语句之前加上关键字 explain / desc

各字段含义
字段含义
idselect查询的序列号,表示查询中执行select子句或者是操作表的顺序 (id相同,执行顺序从上到下;id不同,值越大,越先执行)。
select_type表示 SELECT 的类型,常见的取值有 SIMPLE(简单表,即不使用表连接 或者子查询)、PRIMARY(主查询,即外层的查询)、 UNION(UNION 中的第二个或者后面的查询语句)、 SUBQUERY(SELECT/WHERE之后包含了子查询)等
type表示连接类型,性能由好到差的连接类型为NULL、system、const、 eq_ref、ref、range、 index、all 。
possible_key显示可能应用在这张表上的索引,一个或多个。
key实际使用的索引,如果为NULL,则没有使用索引。
key_len表示索引中使用的字节数, 该值为索引字段最大可能长度,并非实际使用长 度,在不损失精确性的前提下, 长度越短越好 。
rowsMySQL认为必须要执行查询的行数,在innodb引擎的表中,是一个估计值, 可能并不总是准确的。
filtered表示返回结果的行数占需读取行数的百分比, filtered 的值越大越好。
extra

额外信息。这里可以显示一些额外的执行计划信息,如是否使用了临时表、是否需要进行文件排序等。

using index condition : 查找使用了索引,但需要回表查询

using where;using index: 查找使用了索引,在索引中能查到所需的数据,无需回表查询

四、SQL优化

为什么不要使用select *

因为 * 会包含没有创建索引的字段,此时通过索引不能直接查到信息的字段,需要通过id做回表查询,也就是说尽量使用覆盖索引(查询的字段写明,并且这些字段都可以通过走一边索引即可查询到所需的数据,无需回表查询),索引有聚集索引和二级索引两类,聚集索引包含整行数据,二级索引也就是我们对字段创建的索引,只包含该索引字段的数据和id。

以根据用户名查询用户的id例当已经为username创建单列索引时

select * from tb_user where username = '张三' ;

该查询会走username的索引,能走索引查出username 和 id,但是select * 还需要查询其它信息,索引还要根据id在聚集索引中查询其它信息,即回表查询。这样走了两次索引,效率就有所降低。

 而使用以下SQL不用走回表查询时,效率更高:

select id from tb_user where username = '张三' ;

 再以用户名查询用户id、用户名、用户密码为例:

select id,username,password from tb_user where username = '张三' ;

当我们要查询效率更高时,可以为username和password建立联合索引时,不需要走回表查询去查询其它信息,查询效率更高。

插入优化 insert

批量插入,防止频繁的执行SQL语句

insert into tb_user values
('1','张三'),
('2','李四'),
('3','王五');

 手动提交事务,防止事务频繁的开启和提交

start  transaction;
 insert  into  tb_test  values(1,'Tom'),(2,'Cat'),(3,'Jerry');
 insert  into  tb_test  values(4,'Tom'),(5,'Cat'),(6,'Jerry');
 insert  into  tb_test  values(7,'Tom'),(8,'Cat'),(9,'Jerry');
commit;

 主键顺序插入,性能要高于乱序插入

比如,按照主键id  1、2、3、4、5...的顺序插入

大批量数据插入

如果一次性需要插入大批量数据(比如: 几百万的记录),使用insert语句插入性能较低,此时可以使 用MySQL数据库提供的 load 指令进行插入。操作如下:

1、客户端连接服务端时,加上参数 -–local-infile

 mysql –-local-infile  -u  root  -p

 2、设置全局参数local_infile为1,开启从本地加载文件导入数据的开关

set  global  local_infile = 1;

3、执行load指令将准备好的数据,加载到表结构中

load  data  local  infile  '/root/load_user.sql'  into  table  tb_user  fields  terminated  by  ','  lines  terminated  by  '\n' ; 

 其中 /root/load_user.sql 是大批量数据文件的路径

插入到 tb_user 表中,字段之间是 ',' 分割,每行之间是 '\n' 分割

这样插入性能高于insert,若主键是顺序插入性能高于乱序插入

主键优化

在InnoDB存储引擎中,表数据都是根据主键顺序组织存放的,这种存储方式的表称为索引组织表

逻辑存储结构是表空间-->段-->区-->页-->行

页分裂

因为B+Tree索引中,数据都是存储在叶子节点,并且数据是按照索引字段(主键)顺序存放,当乱序插入时,会出现以下情况:

页合并

当相邻两页之间的数据只有50%时,InnoDB会判断是否可以将两页进行合并,若可以则会将该相邻两页的数据进行合并,50%可以在创建表或者创建索引时指定参数MERGE_THRESHOLD设置,默认是50%。

  • 满足业务需求的情况下,尽量降低主键的长度,减小索引体积
  • 插入数据时,尽量选择顺序插入,选择使用AUTO_INCREMENT自增主键。
  • 尽量不要使用UUID做主键或者是其他自然主键,如身份证号。 业务操作时,避免对主键的修改。因为这些都是乱序的主键,会出现页分裂的情况

排序优化 order by

MySQL的排序,有两种方式

        Using filesort : 通过表的索引或全表扫描,读取满足条件的数据行,然后在排序缓冲区sort buffer中完成排序操作,所有不是通过索引直接返回排序结果的排序都叫 FileSort 排序。

        Using index : 通过有序索引顺序扫描直接返回有序数据,这种情况即为 using index,不需要 额外排序,操作效率高。

        Using filesort 通常比使用索引排序慢得多,因为它需要在磁盘上创建临时文件并进行排序操作。这会增加 I/O 操作,从而影响查询性能。在大数据量的情况下,Using filesort 可能会显著降低查询效率。Using index的性能高,而Using filesort的性能低,我们在优化排序 操作时,尽量要优化为 Using index

当根据年龄(age)字段排序查询时,可以看出extra额外信息显示的是Using filesort

当我们对price字段创建了索引进行排序时,正常走索引,效率高,当使用select * 即需要回表查询做排序操作时,还是会另开辟空间做Using filesort 查询

当根据age倒叙排列,而B+Tree中索引中,数据是根据索引字段正序排列,反向扫描索引(Backward index scan;)

 对多字段进行排序:

先对价格(price)进行排序,若价格相同,则根据评分排序:

explain select id, price, score  from tb_hotel order by price, score;

 针对多字段进行排序的情况需要对这多字段创建联合索引,才能让排序走索引:

 这时需要注意,两字段要都是升序或都是降序才能走索引,并且必须是先根据price排序再根据score排序才会走索引,因为这是创建的联合索引,若是先根据score排序则违背了最左前缀法则,不会走索引,Collection列是A表示索引中的数据根据升序排列

 若一个升序一个降序,即price升序,score降序,则根据price排序时会走索引,而price相同时根据score降序排序则不会走索引,这时若想走索引则需要再创建一个索引指定索引中的字段数据price升序,score降序:

创建索引时指定规则(ASC/DESC),默认是升序ASC。

 create index idx_price_score_AD on tb_hotel(price asc,score desc);

 若不得不走缓存区使用Using filesort 进行排序,在大数据量的情况下可以增加缓冲区的大小:

查看缓冲区大小:

show variables like 'sort_buffer_size';

order by优化总结:

  1. 根据排序字段建立合适的索引,多字段排序时,也遵循最左前缀法则。
  2. 尽量使用覆盖索引。
  3. 多字段排序, 一个升序一个降序,此时需要注意联合索引在创建时的规则(ASC/DESC)。
  4. 如果不可避免的出现filesort,大数据量排序时,可以适当增大排序缓冲区大小 sort_buffer_size(默认256k)。 

 分组优化group by

需要对分组优化,同样需要对需要分组的字段添加索引,走索引进行分组查询效率更高,需要注意的是也需要满足最左前缀法则,尽量使用联合索引

没有索引走临时表,type为ALL走全表扫描效率低

 建立索引后:

 联合索引时不满足最左前缀法则:

有where条件时是满足最左前缀法则的,走索引:

limit优化

在数据量比较大时,如果进行limit分页查询,在查询时,越往后,分页查询效率越低。

优化方式:使用覆盖索引子查询形式进行优化。

 explain   select  *  from 
 tb_sku  t,
(select  id  from  tb_sku  order  by  id limit  2000000,10)  a #将该页数据的id查询,然后对做多表查询
where t.id  =  a.id;

 Mysql不支持 in 后加 limit 关键字

count优化

用法:count(*)、count(主键)、count(字段)、count(数字)

  • count(主 键): InnoDB 引擎会遍历整张表,把每一行的 主键id值都取出来,返回给服务层。 服务层拿到主键后,直接按行进行累加(主键不可能为null)
  • count(字 段) :
    • 没有not null 约束 : InnoDB 引擎会遍历整张表把每一行的字段值都取出来,返回给服务层,服务层判断是否为null,不为null,计数累加。
    • not null 约束:InnoDB 引擎会遍历整张表把每一行的字段值都取出来,返回给服务层,直接按行进行累加。
  • count(1): InnoDB 引擎遍历整张表,但不取值。服务层对于返回的每一行,放一个数字“1” 进去,直接按行进行累加。(可以是其它数字)
  • count(*) :InnoDB引擎并不会把全部字段取出来,而是专门做了优化,不取值,服务层直接 按行进行累加。

综上按效率排列:count(字段) < count(主键 id) < count(1) ≈ count(*),所以尽 量使用 count(*)。

update优化

在执行update更新操作时要根据有索引的字段进行更新:

将城市为成都的都改为四川,若city字段没有创建索引,则InnoDB会对整个表tb_hotel都加锁,即表级锁,若事务还未提交,此时就不能执行该表的其它更新操作

若创建了索引,则会对该行数据添加锁,即行级锁。

update tb_hotel set city = '四川' where city = '成都';

在执行上述的SQL时, 当开启多个事务,发现行锁升级为了表锁。 导致该update语句的性能大大降低。会影响效率。

 所以在执行update更新操作时,尽量使用有索引的字段做为where条件

InnoDB的行锁是针对索引加的锁,不是针对记录加的锁 ,并且该索引不能失效,否则会从行锁 升级为表锁 。

\G :SQL最后加,以键值对一列形式返回

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1944461.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Matlab编程资源库(1)选择结构

一、if语句 在 MATLAB 中&#xff0c; if 语句有 3 种格式。 (1) 单分支 if 语句&#xff1a; if 条件 语句组 end 当条件成立时&#xff0c;则执行语句组&#xff0c;执行完之后&#xff0c; 继续执行 if 语句的后继语句&#xff0c;若条件不成 立&#xff0c;则直接执…

什么是PCB流锡槽焊盘/C型焊盘,如何设计?-捷配笔记

在PCB进行机器组装器件时&#xff08;如波峰焊&#xff09;&#xff0c;为了防止部分需要二次焊接的元器件的焊盘堵孔&#xff0c;就需要在PCB焊盘上面开个过锡槽&#xff0c;以便过波峰焊时&#xff0c;这些焊锡会流掉。开流锡槽就是在焊盘裸铜&#xff08;敷锡&#xff09;部…

setsockopt选项对tcp速度

GPT-4 (OpenAI) 每个setsockopt调用都涉及到一个套接字描述符&#xff0c;一个指定网络层的常数&#xff08;如IPPROTO_IP, IPPROTO_TCP, IPPROTO_IPV6, SOL_SOCKET等&#xff09;&#xff0c;一个指定需配置的选项的常数&#xff0c;一个指向配置值的指针&#xff0c;以及那个…

04-数据库MySQL

一、项目要求 二、项目过程介绍 1、新建数据库 2、新建表 3、处理表 1.修改student 表中年龄(sage)字段属性&#xff0c;数据类型由int 改变为smallint 2.为Course表中Cno 课程号字段设置索引,并查看索引 3.为SC表建立按学号(sno)和课程号(cno)组合的升序的主键索引&#xf…

20分钟上手新版Skywalking 9.x APM监控系统

Skywalking https://skywalking.apache.org/ Skywalking是专为微服务、云原生和基于容器的&#xff08;Kubernetes&#xff09;架构设计的分布式系统性能监控工具。 Skywalking关键特性 ● 分布式跟踪 ○ 端到端分布式跟踪。服务拓扑分析、以服务为中心的可观察性和API仪表板。…

英迈中国与 Splashtop 正式达成战略合作协议

2024年7月23日&#xff0c;英迈中国与 Splashtop 正式达成战略合作协议&#xff0c;英迈中国正式成为其在中国区的战略合作伙伴。此次合作将结合 Splashtop 先进的远程桌面控制技术和英迈在技术服务与供应链管理领域的专业优势&#xff0c;为中国地区的用户带来更加安全的远程访…

Android TabLayout的简单用法

TabLayout 注意这里添加tab&#xff0c;使用binding.tabLayout.newTab()进行创建 private fun initTabs() {val tab binding.tabLayout.newTab()tab.text "模板库"binding.tabLayout.addTab(tab)binding.tabLayout.addOnTabSelectedListener(object : TabLayout.On…

【开源库编译 | zlib】 zlib库最新版本(zlib-1.3.1)在Ubuntu(Linux)系统下的 编译 、交叉编译(移植)

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

VSCode | 修改编辑器注释的颜色

1 打开VsCode的设置进入settings.json 2 添加如下代码 "editor.tokenColorCustomizations": {"comments": "#17e917"},3 保存即可生效

第十四届蓝桥杯省赛C++C组C题【三国游戏】题解(AC)

解题思路 由于三种国家都有获胜的可能&#xff0c;所以我们需要分别枚举 X , Y , Z X,Y,Z X,Y,Z 获胜的情况。 设 X X X 获胜&#xff0c;那么对于第 i i i 个事件的贡献为 a [ i ] − ( b [ i ] c [ i ] ) a[i]-(b[i]c[i]) a[i]−(b[i]c[i])&#xff0c;根据贪心的策略…

黑马JavaWeb企业级开发(知识清单)03——HTML实现正文:排版(音视频、换行、段落)、布局标签(div、span)、盒子模型

文章目录 前言一、正文排版1. 视频标签: < video >2. 音频标签: < audio >3. 换行标签: < br >4. 段落标签 < p >5. vscode实现 二、布局1. 盒子模型2. 布局标签< div >和< span >3. VScode实现 三、源代码和运行结果总结 前言 本篇文章是…

鸿蒙HarmonyOS【应用开发一、鸿蒙简介】

✍️作者简介&#xff1a;小北编程&#xff08;专注于HarmonyOS、Android、Java、Web、TCP/IP等技术方向&#xff09; &#x1f433;博客主页&#xff1a; 开源中国、稀土掘金、51cto博客、博客园、知乎、简书、慕课网、CSDN &#x1f514;如果文章对您有一定的帮助请&#x1f…

CSS实现的扫光效果组件

theme: lilsnake 图片和内容如有侵权&#xff0c;及时与我联系~ 详细内容与注释&#xff1a; CSS实现的扫光效果组件 代码 技术栈与框架 Vue3 CSS 扫光效果的原理 扫光效果的原理就是从左到右无限循环的一个位移动画 实现方式 适配文字扫光效果的css .shark-box { …

STL常用算法——常用查找算法

自定义类型都要用仿函数判断 1.find() class Person { public:Person(string name,int age){this->m_Name name;this->m_Age age;}bool operator(const Person &p)//重载operator{if (this->m_Name p.m_Name && this->m_Age p.m_Age){return true;…

CSDN的动态在哪里

模板 文章目录 模板 如果对你有帮助&#xff0c;就点赞收藏把&#xff01;(&#xff61;&#xff65;ω&#xff65;&#xff61;)&#xff89;♡ 早上发了一个动态&#xff0c;这是我第一次发动态&#xff0c;然后却发现我不知道动态在哪打开 我找了好几个地方&#xff0c;然后…

FPGA实验6: 有时钟使能两位十进制计数器的设计

一、实验目的与要求 1.. 熟练掌握使用原理图设计较复杂电路&#xff1b; 2. 学习原理图设计中总线的表示以及使用方法。 二、实验原理 运用Quartus II 集成环境下的图形设计方法设计有时钟使能的两位十进制计数器。进行波形仿真和分析、引脚分配并下载到实验设备上进行功能…

JS进阶之以题悟道(一)列表内容排序再渲染

注释很详细&#xff0c;直接上代码 涉及知识点&#xff1a; 正则表达式outerHTMLjoinmap 题干&#xff1a; 我的答案 <!DOCTYPE html> <html><head><meta charset"utf-8" /><meta name"viewport" content"widthdevice-wid…

py3.7.4离线安装openpyxl等错误,无法安装openpyxl...

&#x1f3c6;本文收录于《CSDN问答解答》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&…

网络安全等级保护:什么是网络安全等级保护?(非常详细)零基础入门到精通,收藏这一篇就够了

关键词&#xff1a; 网络安全等级保护 等级保护 网络 信息系统 旧话重提&#xff0c;一直以来&#xff0c;我们不断强调“等级保护”制度是我国的网络安全领域的基本制度、基本策略和基本方法&#xff0c;是促进信息化健康发展&#xff0c;维护国家安全、社会秩序和公共利益的…

【计算机毕业设计】基于微信小程序的传染病防控宣传系统【源码+lw+部署文档】

包含论文源码的压缩包较大&#xff0c;请私信或者加我的绿色小软件获取 免责声明&#xff1a;资料部分来源于合法的互联网渠道收集和整理&#xff0c;部分自己学习积累成果&#xff0c;供大家学习参考与交流。收取的费用仅用于收集和整理资料耗费时间的酬劳。 本人尊重原创作者…