mysql索引_MySQL索引介绍和实战

索引是什么

MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。

可以得到索引的本质:索引是数据结构,索引的目的是提高查询效率,可以类比英语新华字典,根据目录定位词语

如果没有目录呢,就需要从A到Z,去遍历的查找一遍,一个一个找和直接根据目录定位到数据,差的就是天壤之别

索引底层数据结构

数据库除了存储数据本身之外,还维护着一个满足特定查找算法的数据结构,这些结构以某种方式指向数据,这样就可以基于这些数据结构实现高效查找算法。这种结构就是索引,MySQL中索引是B+树实现的,每个索引都对应一棵B+树

6a02a969f2fe3da45b3c3adebee757dd.png

索引的优势

提高数据检索效率,降低数据库IO成本

通过索引列对数据进行排序,降低数据排序成本,降低了CPU消耗

索引的劣势

一个索引都为对应一棵B+树,树中每一个节点都是一个数据页,一个页默认会占用16KB的存储空间,所以一个索引也是会占用磁盘空间的。(空间的代价)

索引是对数据的排序,当对表中的数据进行增、删、改操作时,都要维护修改内容涉及到的B+树索引。所以在进行这些操作时需要额外的时间进行一些记录移动,页面分裂、页面回收等操作来维护索引(时间上的代价)

索引语法

以test_user表为例,建表sql如下

CREATE TABLE`test_user` (

`id`int(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',

`user_id` varchar(36) NOT NULL COMMENT '用户id',

`user_name` varchar(30) NOT NULL COMMENT '用户名称',

`phone`varchar(20) NOT NULL COMMENT '手机号码',

`lan_id`int(9) NOT NULL COMMENT '本地网',

`region_id`int(9) NOT NULL COMMENT '区域',

`create_time`datetime NOT NULL COMMENT '创建时间',PRIMARY KEY(`id`),KEY `idx_user_id` (`user_id`)

) ENGINE=InnoDB AUTO_INCREMENT=1010001 DEFAULT CHARSET=utf8mb4;

1.查看索引:SHOW INDEX FROM table_name\G

SHOW INDEX FROM test_user;

4e564236426badd02b30321dfe1adbca.png

2.删除索引:DROP INDEX [indexName] ON mytable;

DROP INDEX idx_user_id ON test_user;

0e2631dd6a53b353c584e1f88136abba.png

3.创建索引 alter tableName add [unique] index [indexName] on (columnName (length) )

ALTER TABLE test_user ADD INDEX idx_user_id(user_id);

d151917386788c500c33db24237fc3d6.png

哪些情况需要建索引

主键自动建立唯一索引

频繁作为查询的条件的字段应该创建索引

查询中与其他表关联的字段,外键关系建立索引

频繁更新的字段不适合创建索引:因为每次更新不单单是更新了记录还会更新索引,加重IO负担

Where条件里用不到的字段不创建索引

单间/组合索引的选择问题(在高并发下倾向创建组合索引)

查询中排序的字段,若通过索引去访问将大大提高排序的速度

查询中统计或者分组字段

哪些不适合建索引

表记录太少

经常增删改的表

数据重复且分布平均的表字段,如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果。

索引实战

我们在test_user表中有100万数据

4409aef8fc0a6b01822cbef6a0f16e5d.png

优化一:使用全部索引

1.不加索引,关闭缓存查一条数据

SELECT SQL_NO_CACHE * FROM `test_user` WHERE phone='15190427892' AND lan_id=317 AND region_id=92

605971eca37e7e8e68f7992b07d9fe9c.png

2.加一条复合索引

ALTER TABLE test_user ADD INDEX idx_phone_lan_region(phone,lan_id,region_id);

再查一次,看结果

ddf48e13e9c3f948142d4f8d92fe4ab9.png

可以看到,加了索引以后,查询效率提高了很多

这里我们建立的复合索引包含的3个字段,查询的时候全部用到了,而且where中的条件严格按照索引顺序,这样查询效率是最高的

我们使用EXPLAIN关键字看一下

37ca17c89b8f5c5261d607976eb22063.png

优化二:最左前缀法则

我们把上面那个例子的第一个插件条件删掉

EXPLAIN SELECT SQL_NO_CACHE * FROM `test_user` WHERE lan_id=317 AND region_id=92;

我们使用EXPLAIN关键字看一下

de2c1486a74d724ae04e745340f193e0.png

因此,我们得出结论:如果建立的是复合索引,索引的顺序要按照建立时的顺序,即从左到右,如:a->b->c(和 B+树的数据结构有关)

无效索引举例

a->c:a 有效,c 无效

b->c:b、c 都无效

c:c 无效

优化三:不要对索引做以下处理

计算,如:+、-、*、/、!=、<>、is null、is not null、or

函数,如:sum()、round()等等

手动/自动类型转换,如:id = "1",本来是数字,给写成字符串了

我们以!=为例演示,我们使用EXPLAIN关键字看一下

a727dd30234b55b267323ef744915b87.png

优化四:索引不要放在范围查询右边

比如复合索引:a->b->c,当 where a="" and b>10 and c="",这时候只能用到 a 和 b,c 用不到索引,因为在范围之后索引都失效(和 B+树结构有关)

如下

EXPLAIN SELECT SQL_NO_CACHE * FROM `test_user` WHERE phone='15190427892' AND lan_id>317 AND region_id=92;

我们使用EXPLAIN关键字看一下

4ccadb63f203e0308178b0dc019e6353.png

我们把最后一个条件删除,再看一下

91c2553f39ee6ca5ed349f79220c0a0d.png

优化五:减少 select * 的使用

select *会查询很多不必要的字段,造成不必要的网络传输和IO消耗

优化六:like 模糊搜索

失效情况

like "%张三%"

like "%张三"

4ff84f17bac4e9baad7cc01d813da118.png

解决方案

使用复合索引,即 like 字段是 select 的查询字段,如:select name from table where name like "%张三%"

使用 like "张三%"

ec00941b313db3ecc44f8f6780aeebb1.png

1bcfd4a01f70249eeac45f852fd064ad.png

优化七:order by 优化

当查询语句中使用 order by 进行排序时,如果没有使用索引进行排序,会出现 filesort 文件内排序,这种情况在数据量大或者并发高的时候,会有性能问题,需要优化。

filesort 出现的情况举例

order by 字段不是索引字段

order by 字段是索引字段,但是 select 中没有使用覆盖索引,如:select * from staffs order by age asc;

order by 中同时存在 ASC 升序排序和 DESC 降序排序,如:select a, b from staffs order by a desc, b asc;

order by 多个字段排序时,不是按照索引顺序进行 order by,即不是按照最左前缀法则,如:select a, b from staffs order by b asc, a asc;

如下情况没有索引

21e385fb31d45ef1846ebd10ebdf9233.png

filesort 文件内排序会在内存开辟一块空间,然后把数据复制了一份放到这个空间内,再进行排序,这个是很影响性能的

我们可以为这个字段建一个索引

ALTER TABLE test_user ADD INDEX idx_create_time(create_time);

0208c0b38110e739d3249c5e0e8cf706.png

索引层面解决方法

使用主键索引排序

按照最左前缀法则,并且使用覆盖索引排序,多个字段排序时,保持排序方向一致

在 SQL 语句中强制指定使用某索引,force index(索引名字)

不在数据库中排序,在代码层面排序

优化八:group by

其原理也是先排序后分组,其优化方式可参考order by。where高于having,能写在where限定的条件就不要去having限定了。

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

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

相关文章

mysql自增字段_MySQL自增字段的常用语句

学习MySQL数据库&#xff0c;MySQL自增字段是最基础的部分之一&#xff0c;下面为您介绍一些MySQL自增字段的常用语句&#xff0c;希望对您学习MySQL自增字段能些许帮助。1、创建表格时添加&#xff1a; create table table1(id int auto_increment primary key,...)2、创建表格…

mysql安装需要注意什么意思_mysql 安装过程及注意事项

1.1. 下载&#xff1a;我下载的是64位系统的zip包&#xff1a;下载zip的包&#xff1a;下载后解压&#xff1a;D:\软件安装包\mysql-5.7.20-winx641.2. 配置环境变量&#xff1a;变量名&#xff1a;MYSQL_HOME变量值&#xff1a;E:\mysql-5.7.20-winx64path里添加&#xff1a;%…

mysql 语句检查_mysql查询语句

一、简单查询1.最简单查询(查所有数据)select * from 表名 注意&#xff1a;* 代表所有列&#xff0c;并不是代表所有行例&#xff1a;select * from test2.查询指定列select 列名,列名 from 表名例&#xff1a;select code,name from test3.修改结果集的列名 asselect 列名 …

mysql索引 物理文件_MySQL体系结构之物理文件

一、MySQL日志文件mysql日志文件及功能&#xff1a;日志文件功能错误日志记录启动、停止、运行过程中mysqld时出现的问题通用日志记录建立客户端连接和执行的语句二进制日志记录更改数据的所有语句&#xff0c;还用于复制慢查询日志记录执行时间超过long_query_time秒的所有查询…

mysql每次查询1000条数据库_30多条mysql数据库优化方法,千万级数据库记录查询轻松解决...

1.对查询进行优化&#xff0c;应尽量避免全表扫描&#xff0c;首先应考虑在 where 及 order by 涉及的列上建立索引。2.应尽量避免在 where 子句中对字段进行 null 值判断&#xff0c;否则将导致引擎放弃使用索引而进行全表扫描&#xff0c;Sql 代码 : select id from t where …

mysql count转字符串_MySQL字符串函数

把字符串转成小写mysql> select sex,LCASE(job) from string_test where jobDUCK;------------------| sex | LCASE(job) |------------------| 1 | duck |------------------1 row in set (0.00 sec)3&#xff0c;FIND_IN_SET(str,strlist)4&#xff0c;FIELD(str,str1,str…

gitlab 端口_安装Gitlab-注意端口

文档本身并没有什么特殊&#xff0c;安装也很简单&#xff0c;只是修改端口这里如果有需要的可以看一下安装Gitlab[rootdeploy ~]# sudo yum -y install gitlab-ce默认端口是8080&#xff0c;避免冲突还是修改一下[rootlocalhost ~]# cat /etc/gitlab/gitlab.rb |grep 192.168.…

MySQL read-c_技术分享 | MySQL C API 参数 MYSQL_OPT_READ_TIMEOUT 的一些行为分析

作者&#xff1a;戴岳兵MYSQL_OPT_READ_TIMEOUT 是 MySQL c api 客户端中用来设置读取超时时间的参数。在 MySQL 的官方文档中&#xff0c;该参数的描述是这样的&#xff1a;MYSQL_OPT_READ_TIMEOUT (argument type: unsigned int *)The timeout in seconds for each attempt t…

mysql出现core dumped_mysql-为什么我遇到分段错误(核心已转储)?

这是我要运行的代码.它可以编译,并且工作良好,直到昨天.#include #include int main(int argc, char **argv){MYSQL *conn;MYSQL_RES *result;MYSQL_ROW row;int num_fields;int i;conn mysql_init(NULL);mysql_real_connect(conn, "hostname", "username"…

mysql解释中fitered_MySQL的explain中的参数说明

1、id每个被独立执行的操作的标识&#xff0c;表示对象被操作的顺序&#xff1b;id值大&#xff0c;先被执行&#xff1b;如果相同&#xff0c;执行顺序从上到下。若没有子查询和联合查询&#xff0c;id则都是1。Mysql会按照id从大到小的顺序执行query&#xff0c;在id相同的情…

vue脚手架搭建项目_复习之vue脚手架搭建项目的两种方法

安装脚手架node 版本要求&#xff1a; > 8.9 。关于旧版本&#xff1a;如果在这之前已经全局安装了旧版本的vue-cli(1.x 或 2.x)&#xff0c;那么需要先卸载掉。卸载旧版本运行&#xff1a;npm uninstall vue-cli -g 或 yarn global remove vue-cli。安装vue/cli&#xff1a…

ubuntu修改mysql账户密码_Ubuntu修改mysql用户重置密码

编辑mysql的配置文件/etc/mysql/my.cnf&#xff0c;或者/etc/mysql//mysql.conf.d/mysqld.cnf,在[mysqld]段下加入一行“skip-grant-tables”。1、安装$ sudo apt-get install mysql-server$ apt install mysql-client$ apt install libmysqlclient-dev以此在终端输入上述代码&…

pythonsocket中tcp通信接收不到数据_TCP 为什么三次握手而不是两次握手(正解版)...

先说结论为了实现可靠数据传输&#xff0c; TCP 协议的通信双方&#xff0c; 都必须维护一个序列号&#xff0c; 以标识发送出去的数据包中&#xff0c; 哪些是已经被对方收到的。 三次握手的过程即是通信双方相互告知序列号起始值&#xff0c; 并确认对方已经收到了序列号起始…

mysql高级查询面试_高级MySQL数据库面试问题 附答案

因为有大家的支持&#xff0c;我们才能做到现在&#xff0c;感谢你们这一路上对我们的支持.在这篇文章中&#xff0c;我们将主要针对MySQL的实用技巧&#xff0c;讲讲面试中相关的问题.1. 如何使用SELECT语句找到你正在运行的服务器的版本并打印出当前数据库的名称?答&#xf…

ecshop清除mysql缓存_ECSHOP缓存清理关闭教程

ECSHOP的缓存存放在templates/caches/文章夹下&#xff0c;时间长了这个文件夹就会非常庞大&#xff0c;拖慢网站速度。还有很多情况我们不需要他的缓存。本文介绍禁用ECSHOP缓存的方法。ECSHOP的缓存有两部分&#xff0c;一部分是SMARTY的页面缓存&#xff1b;另一部分是SQL查…

mysql无法启动如何备份文件_mysql 5.7 停电导致无法启动、如何备份数据,重新安装mysql...

用于记录服务器停电导致&#xff0c;mysql启动失败后&#xff0c;如何备份数据&#xff0c;重新安装mysql&#xff0c;主要分为数据备份&#xff0c;mysql重新安装。1、mysql无法启动时&#xff0c;进行数据备份。执行&#xff1a;systemctl start mysqld&#xff0c;启动失败。…

python tkinter entry默认值_Python ---(六)Tkinter窗口组件:Entry

The Tkinter Entry Widget##简介Entry(输入框)组件通常用于获取用户的输入文本。##何时使用 Entry 组件&#xff1f;Entry 组件仅允许用于输入一行文本&#xff0c;如果用于输入的字符串长度比该组件可显示空间更长&#xff0c;那内容将被滚动。这意味着该字符串将不能被全部看…

java不显示图片_Java图片显示不出来,怎么解决

展开全部有两个问题&#xff1a;图片路径没有写对&#xff0c;图片在 src 下&#xff0c;图片路径应是 src/海洋.png&#xff0c;正e68a84e8a2ad62616964757a686964616f31333365656632确的写法应是 image new ImageIcon("src/海洋.png")image new ImageIcon("…

memcached的java客户端_Memcached Java客户端

代码示例&#xff1a;import com.danga.MemCached.*;import org.apache.log4j.*;public class TestMemcached {public static void main(String[] args) {/*初始化SockIOPool&#xff0c;管理memcached的连接池*/String[] servers { "192.168.1.20:12111" };SockIOP…

java 静态块初始化_简单了解java中静态初始化块的执行顺序

这篇文章主要介绍了简单了解java中静态初始化块的执行顺序,文中通过示例代码介绍的非常详细&#xff0c;对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下在java中&#xff0c;其应该是先于所有的方法执行。下面是测试代码&#xff1a;public class Test1 {st…