- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
索引是mysql数据库中的一种数据结构,就是一种数据的组织方式,这种数据结构又称为key
表中的一行行数据按照索引规定的结构组织成了一种树型结构,该树叫B+树
优化查询速度
注意:只能加速索引字段
错误的认知
项目上线之后,运行了一段是时间,发现项目运行极卡
想要加索引,最好提前加上,在开发之初,定位到常用的查询,为该字段提前创建索引,
在上线之后想加索引,光把问题定位到索引上就需要耗费很长时间,排查成本很高
索引越多越好
索引使用与加速查询的,降低写效率
如果某一张表的ibd文件中创建了很多棵索引树,意味着很小一个updata语句就会导致很多棵索引数都需要发生变化,从而把硬盘io打上去
索引的根本原理就是把硬盘的io次数降下来
为一张表中的一行行记录创建索引就是为书的一页页内容创建目录
有了目录以后,我们以后的查询都应该通过目录去查询
一次磁盘io带来的影响
7200转/分钟
120转/s
慢在找的过程,读的过程是快的,(统称延迟时间)
一次io的延迟时间=平均寻道时间(大概需要5ms)+平均延迟时间(4ms)---》9ms
9ms对于一个人来说是很慢的,但是对于计算机来说是很长的,比如一台500 -MIPS 的机器每秒可以执行5亿条指令,应为指令是靠电的性质,换句话说就是执行一次io的时间可以执行450万条指令,数据动则十万百万乃至千万条数据,每次9ms的时间显然是一个灾难。
磁盘的预读
innodb存储引擎一页16k,即一次io读16k,
当一次io时,不光把当前磁盘地址的数据,而是把相邻的数据也都读取到内存缓存区内,因为局部预读性原理告诉我们,当计算机访问一个地址的数据的时候,与其相邻的数据也会很快被访问到。
crate index xxx on user(id);
创建索引最好是以占空间小,重复度低的字段创建索引
innodb存储引擎默认的索引结构为B+ 树,而B+树是由二叉树、平衡二叉树、B树演变而来的。
二叉树——》平衡二叉树——》B 树 ——》B + 树
基本概念:
leaf node:叶子节点
non-leaf node:根节点、树枝节点
二叉树:
二叉树有一个特点,它的左节点的 key 值小于当前节点的 key 值,而它的右节点 key 值大于当前节点 key 值。
创建二叉树索引
取每一条记录的id值作为key值,value为本行完整记录,构建了树型结构后,查找的速度根树的高度有关系。
平衡二叉树:
平衡二叉树又称为AVL树,指的就是左子树的高度与右子树的高度相差不超过1,如下图所示;
平衡二叉树相比于二叉树来说,查找效率更稳定,总体的查找速度也更快,但是并不是基于平衡二叉树构建索引就可以的。因为每个磁盘块只放一个节点,每个节点只放一组键值对,当数据过大的时候,二叉树的节点就会非常多,树的高度也会变高,查找的效率也会变低!
B 树:
就是构建一个单节点可以存储多个键值对的平衡树,就是B树。
B树相对于平衡二叉树,每个节点存储了更多的键值和数据,每个节点有更多的子节点,子节点的个数称为阶,上图就是一个3阶B树,高度也会很低,这样B树的查找磁盘次数也会很少,这样数据的查找效率就会比平衡二叉树高。
B+ 树:
B+ 树是对B树的进一步优化。
B+ 树和B 树有什么不同
3*3*3=9
个数据。所以如果我们的B+ 树一个节点可以存储1000个键值,那么3层B+ 树可以存储1000*1000*1000=10亿
个数据。而一般节点是常驻内存的,所以一般我们查找出10亿数据,只需要2次磁盘IO。而且B+ 树中各个页之间也是通过双向链表连接的,叶子节点找那个的数据是通过单向链表连接的。其实在B 树中我们也可以多各个节点加上链表。其实这些不是它们之间的区别,是因为在mysql的innodb存储引擎中,索引及时这样存储的。也就是说B+ 树索引就是innodb中 B+ 树索引真正的实现方式,准确的说应该是聚集索引。
在innodb中,我们通过数据页之间通过双向链表连接以及叶子节点中数据之间通过单向链表连接的方式可以找到表中所有的数据。
聚集索引、聚簇索引、主键索引:
以主键字段值为key构建的B+ 树,改B+ 树的叶子节点放的是主键值与本行完整的记录。
即:表中的数据都聚聚在叶子节点中,所以称之为聚集索引。
非聚集索引、非聚簇索引、辅助索引、二级索引:
以非主键字段值为key构成的B+ 树,改B+ 树的叶子节点放的是key与其主键对应的字段值。
补充:一张innodb 存储引擎中有且只能有一张聚集索引,但是可以有多个非聚集索引(辅助索引)
聚集索引负责聚集整张表的所有的数据,而辅助索引是专门提速来用
覆盖了索引:在命中了索引的基础上,只在本索引树的叶子节点就找到了我们想要的数据。
回表操作:在命中了辅助索引的基础上,在辅助索引的叶子节点并没有找想要的数据,需要拿到对应的主键字段值去聚集索引去找。
举例:假设我有一张表,我们这张表是以ID字段为基础创建的主键索引,我是以name字段创建的辅助索引
主键索引——》id字段
辅助索引——》name字段
select name, age, gender from user where name='yang';
这个命中了辅助索引,那么就顺着索引树从根节点一路找下去,找到叶子节点后,叶子节点放的是 ‘yang’ 这个人名以及它的主键字段值
但是我要的是name age gender ,我要的不是id值和主键值,如果我要的是主键值和id值那么我就不需要去其他地方找了——》这就叫覆盖了索引。
因为在自己本索引树的,本索引树的就能找到自己想要的数据,就不需要去别的地方找
但是这并不是我想要的,那么我要拿着我 ‘yang’的主键字段值假如是3,就回过头继续去主键索引树根节点继续找到我想要的叶子节点的数据,那里面所有数据都有——》这就叫回表操作
提问:
1、命中了辅助索引的前提下能不能覆盖了索引?
可能是!向这种情况下就是select name, id from user where name='yang'; '
这就不是select name, age, gender from user where name='yang';
2、如果命中了主键索引是否覆盖了索引?
一定是!·select name, age, gender from user where id=3;
所以一个SQL语句查询的字段尽量不要想写什么就写什么甚至是 * ,要尽量覆盖了索引。
MySQL常用的索引分类
聚集索引:即主键索引,primary key
用途:
1.加速查找
2.约束(不为空,不能重复)
辅助索引:
唯一索引:unique
用途:
1.加速查找
2.约束(不能重复)
普通索引:index
用途:
1.加速查找
创建聚集索引
alter table 表名 add prmary key 表名(字段名);
alter table 表名 drop primary key;——>删除
创建唯一索引
alter table 表名 add unique key 表名(字段名); 没有写索引名 show create table 表名; 查看
alter table 表名 drop index 索引名;——>删除
创建普通索引
创建表时
create table 表名(
id int primary key auto_increment,
class_name varchar(10) unique,
name varchar(16),
age int
);
创建表后
create index 索引名 on 表名(字段名);
drop index 索引名 on 表名;——>删除
create index zz on t1(id, name,age)
例如:有这样的数据
id name age gender email
1 yang1 18 male yy@qq.com
2 yang2 28 female yy@qq.com
3 yang3 38 male yy@qq.com
4 yang4 48 female yy@qq.com
我现在对它们建联合索引,那么我每条记录提取的key就是 id,name,value对应的是该条记录,列如:
1,yang1,18 ————>对应 1 yang1 18 male yy@qq.com
2,yang2, 28 ————>对应 2 yang2 28 female yy@qq.com
那么,当初只有一个字段的时候比大小的时候很好比,那两个字段值怎么比大小?
1,yang1,18
2,yang2,28
注意这个和字符串比大小一样,从左到右一个一个比,第一个如果分胜负了,就没有必要在比联合的了第二个字段了
在查询条件中出现了id name,age字段那么就肯定能命中这个联合索引
但是必须带着id、例如:id name、id age、id age name
最核心的原理就是每次从最左边第一个位置开始比大小,通过最左边就能够缩小范围,这就是最左前缀匹配原则。
什么时候建立联合索引?
联合索引就只有一棵树,当不用联合索引聚集索引和辅助索引就需要建三棵树,这样就浪费了空间。
如果要平凡的用这几个字段来一起查询,就可以考虑建立联合索引,就一棵树。
但是注意在查询条件中一定要带有最左边的字段
总结:如果查询条件中涉及到多个字段值,这多个字段值有一个同性,大家都会带着某一个字段,那这时候就可以键联合索引。
学习之旅
目前我正在构建相当大的网络系统,我需要强大的 SQL 数据库解决方案。我选择 Mysql 而不是 Postgres,因为一些任务需要只读(MyISAM 引擎)而其他任务需要大量写入(InnoDB)。
我在 mysql 中使用如下命令。当它显示表格数据时,它被格式化为一个非常干净的表格,间距均匀且 |作为列分隔符。 SELECT * FROM TABLE_NAME; 当我从 CLI 运行命令时,如下
我知道这个问题之前已经被问过好几次了,我已经解决了很多问题,但到目前为止没有任何效果。 MySQL 试图将自身安装到的目录 (usr/local/mysql) 肯定有问题。关于我的错误的奇怪之处在于我
以下是我的 SQL 数据结构,我正在尝试如下两个查询: Select Wrk_ID, Wrk_LastName, Skill_Desc from Worker, Skill where
我们有一个本地 mysql 服务器(不在公共(public)域上),并希望将该服务器复制到我们拥有的 google 云 sql 实例。我的问题是:1.这可能吗?2.我们的本地服务器只能在本地网络上访问
我有一个表(test_table),其中一些字段值(例如字段 A、B 和 C)是从外部应用程序插入的,还有一个字段(字段 D),我想从现有表(store_table)插入其值,但在插入前者(A、B 和
我想创建一个 AWS RDS 实例,然后使用 terraform 管理数据库用户。因此,首先,我创建了一个 RDS 实例,然后使用创建的 RDS 实例初始化 mysql 提供程序,以进一步将其用于用户
当用户在我的网站上注册时,他们会在我的一个数据库中创建自己的表格。该表存储用户发布的所有帖子。我还想做的是也为他们生成自己的 MySql 用户——该用户仅有权从他们的表中读取、写入和删除。 创建它应该
我有一个关于 ColdFusion 和 Mysql 的问题。我有两个表:PRODUCT 和 PRODUCT_CAT。我想列出包含一些标记为:IS_EXTRANET=1 的特殊产品的类别。所以我写了这个
我想获取 recipes_id 列的值,以获取包含 ingredient_id 的 2,17 和 26 条目的值。 假设 ingredient_id 2 丢失则不获取记录。 我已经尝试过 IN 运算符
在 Ubuntu 中,我通常安装两者,但 MySQL 的客户端和服务器之间有什么区别。 作为奖励,当一个新语句提到它需要 MySQL 5.x 时,它是指客户端、服务器还是两者兼而有之。例如这个链接ht
我重新访问了我的数据库并注意到我有一些 INT 类型的主键。 这还不够独特,所以我想我会有一个指导。 我来自微软 sql 背景,在 ssms 中你可以 选择类型为“uniqeidentifier”并自
我的系统上有 MySQL,我正在尝试确定它是 Oracle MySQL 还是 MySQL。 Oracle MySQL 有区别吗: http://www.oracle.com/us/products/m
我是在生产 MySQL 中运行的应用程序的新维护者。之前的维护者已经离开,留下的文档很少,而且联系不上了。 我面临的问题是执行以下请求大约需要 10 秒: SELECT COUNT(*) FROM `
我有两个位于不同机器上的 MySQL 数据库。我想自动将数据从一台服务器传输到另一台服务器。比方说,我希望每天早上 4:00 进行数据传输。 可以吗?是否有任何 MySQL 内置功能可以让我们做到这一
有什么方法可以使用 jdbc 查询位于 mysql 根目录之外的目录中的 mysql 表,还是必须将它们移动到 mysql 根目录内的数据库文件夹中?我在 Google 上搜索时没有找到任何东西。 最
我在 mysql 数据库中有两个表。成员和 ClassNumbers。两个表都有一个付费年份字段,都有一个代码字段。我想用代码数字表中的值更新成员表中的付费年份,其中成员中的代码与 ClassNumb
情况:我有 2 台服务器,其中一台当前托管一个实时 WordPress 站点,我希望能够将该站点转移到另一台服务器,以防第一台服务器出现故障。传输源文件很容易;传输数据库是我需要弄清楚如何做的。两台服
Phpmyadmin 有一个功能是“复制数据库到”..有没有mysql查询来写这个函数?类似于将 db A 复制到新的 db B。 最佳答案 首先创建复制数据库: CREATE DATABASE du
我有一个使用 mySQL 作为后端的库存软件。我已经在我的计算机上对其进行了测试,并且运行良好。 当我在计算机上安装我的软件时,我必须执行以下步骤: 安装 mySQL 服务器 将用户名指定为“root
我是一名优秀的程序员,十分优秀!