数据库知识补漏

动态sql

foreach

在这里插入图片描述
在这里插入图片描述

共性sql语句提取

<sql id="getQuery">
        from cj_single_battery  a,
             (
                 select cj_single_no, max(createtime) createtime
                 from cj_single_battery
                 where cj_battery_group_id = (
                     select cj_id
                     from cj_eqm_information
                     where cj_battery_group_no = #{groupNo,jdbcType=VARCHAR}
        )
        group by cj_single_no
        )b
        where
        a.createtime = b.createtime
        and
        a.cj_single_no = b.cj_single_no
        and
        cj_battery_group_id = (
        select cj_id
        from cj_eqm_information
        where cj_battery_group_no =  #{groupNo,jdbcType=VARCHAR}
        )
    </sql>
    <select id="queryBatRealTimeDataByGroupNo" resultType="com.sgcis.icharge.system.system.model.BatRealDate">
        select
               a.cj_single_no cjSingleNo,
               a.batVoltage_work / 1000 as batVoltage,
               a.soc, a.batStatus as status,
               a.batCurrent
       <include refid="getQuery" />
    </select>
    <select id="queryInfo" resultType="com.sgcis.icharge.system.system.model.BatRealDate">
        select
            MAX(a.batVoltage_work / 1000) as maxVal,
            MIN(a.batVoltage_work / 1000) as minVal,
            AVG(a.batVoltage_work / 1000) as avgVal
        <include refid="getQuery" />
    </select>

@JsonProperty注解主要用于实体类的属性上,作用可以简单的理解为在反序列化的时候给属性重命名(多一个名字来识别)
使用此注解时,类必须实现序列化(implements Serializable)

数据库字段为v_switch_id,返回字段属性必须为vSwitchId时候,mybatisplus会自动转化为vswitchId,不能达到要求
@JsonProperty(value = “vSwitchId”)
private String vSwitchId;

用于解决字符串失真问题
@JsonSerialize(using = ToStringSerializer.class)
private Long userId;

索引

优点:
1.通过创建索引,可以在查询的过程中,提高系统的性能;
2. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性;
3. 在使用分组和排序子句进行数据检索时,可以减少查询中分组和排序的时间;

聚集索引与非聚集索引

聚集索引
key- v结构

hash表

哈希表是键值对的集合,通过键(key)即可快速取出对应的值(value),因此哈希表可以快速检索数据(接近 O(1))。

既然哈希表这么快,为什么MySQL 没有使用其作为索引的数据结构呢?
1.Hash 冲突问题 :我们上面也提到过Hash 冲突了,不过对于数据库来说这还不算最大的缺点。
2.Hash 索引不支持顺序和范围查询(Hash 索引不支持顺序和范围查询是它最大的缺点: 假如我们要对表中的数据进行排序或者进行范围查询,那 Hash 索引可就不行了。

红黑树

JDK1.8 以后HashMap为了减少链表过长的时候搜索时间过长引入了红黑树。

二叉树

二叉树是每个结点最多有两个子树的树结构。
无序的一组数[35 27 48 12 29 38 55],一系列的插入操作之后,原本无序的一组数已经变成一个有序的结构了
在这里插入图片描述
如果同样是上面那一组数,我们自己升序排列后再插入,也就是说按照[12 27 29 35 38 48 55]的顺序插入
在这里插入图片描述由于是升序插入,新插入的数据总是比已存在的结点数据都要大,所以每次都会往结点的右边插入,最终导致这棵树严重偏科!!!上图就是最坏的情况,也就是一棵树退化为一个线性链表了,这样查找效率自然就低了,完全没有发挥树的优势了呢!
为了较大发挥二叉树的查找效率,让二叉树不再偏科,保持各科平衡,所以有了平衡二叉树!

平衡二叉树

平衡二叉树是一种特殊的二叉树,所以他也满足前面说到的二叉树的两个特性,同时还有一个特性:
它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
[12 27 29 35 38 48 55]的顺序插入一颗平衡二叉树(通过一系列的左旋右旋)
在这里插入图片描述
满足平衡二叉树的几个特性而保持平衡!这样我们的树也不会退化为线性链表了!查找一个数的时候就能沿着树根一直往下找,这样的查找效率和二分法查找是一样的!如果数据量太大那么这棵树深度变深,影响查询速率
一颗平衡二叉树能容纳多少的结点呢?这跟树的高度是有关系的,假设树的高度为h,那每一层最多容纳的结点数量为2(n-1),整棵树最多容纳节点数为20+21+22+…+2^(h-1)。这样计算,100w数据树的高度大概在20左右,那也就是说从有着100w条数据的平衡二叉树中找一个数据,最坏的情况下需要20次查找。如果是内存操作,效率也是很高的!但是我们数据库中的数据基本都是放在磁盘中的,每读取一个二叉树的结点就是一次磁盘IO,这样我们找一条数据如果要经过20次磁盘的IO?那性能就成了一个很大的问题了!
能不能让他的高度变低,存的数又多,B树出现(B-树)

B树

在B-Tree中,每个结点都可能包含多个元素,并且非叶子结点在元素的左右都有指向子结点的指针。把原来有序的二叉树变成有序多叉树,叶子节点和非叶子节点存储索引和数据
特点:1、每个结点最多m个子结点。
2、除了根结点和叶子结点外,每个结点最少有m/2(向上取整)个子结点。
3、如果根结点不是叶子结点,那根结点至少包含两个子结点。
4、所有的叶子结点都位于同一层。
5、每个结点都包含k个元素(关键字),这里m/2≤k<m,这里m/2向下取整。
6、每个节点中的元素(关键字)从小到大排列。
7、每个元素(关键字)字左结点的值,都小于或等于该元素(关键字)。右结点的值都大于或等于该元素(关键字)
在这里插入图片描述

B+树

非叶子节点不存储数据,叶子节点才存储数据
mysql的B+树一般是三层或者四层,超过则考虑分库分表
B+Tree是在B-Tree基础上的一种优化,使其更适合实现外存储索引结构。B+Tree与B-Tree的结构很像,但是也有几个自己的特性:
1、所有的非叶子节点只存储关键字信息。
2、所有卫星数据(具体数据)都存在叶子结点中。
3、所有的叶子结点中包含了全部元素的信息。
4、所有叶子节点之间都有一个链指针。
在这里插入图片描述位于同一个磁盘块中的数据会被一次性读取出来,而不是需要什么取什么

回表

一张表中有id,name.sex,age四个字段,id为主键,name是索引列
select * from table where name = “张三”
先根据name(普通索引)索引查询id(聚簇索引),再根据id查询整行记录,走了俩个B+树,这种现象叫做回表

索引覆盖(效率较高)

select id,name from table where name = “张三”
根据name可以直接查询到id,name俩个列的值,直接返回即可,不需要从聚簇索引查询任何数据,此时叫做覆盖索引

最左匹配原则

一张表中有id,name.sex,age四个字段,id为主键,name,age是组合索引列
组合索引使用的时候必须先匹配name,然后匹配age
1.select * from table where name = “张三” and age=17 用
2.select * from table where name = “张三” 用
3.select * from table where age=17 不用
4.select * from table where age=17 and name = “张三” 用
为什么4会用组合索引呢?
mysql内部有优化器,会调整对应的顺序,最左匹配原则

组合索引

组合索引结构:俩列先比较第一列然后比较第二列

所有的非聚簇索引都指向聚簇索引

在满足业务需求的情况下,主键自增,

索引下推

一张表中有id,name.sex,age四个字段,id为主键,name,age是组合索引列
select * from table where name = “张三” and age=17
在没有索引下推之前:先根据name从存储引擎中获取符合规则的数据然后再server层对age进行过滤
有索引下推之后,根据name和age俩个条件来从存储引擎中获取对应的数据
三层架构
客户端client
服务端server
存储引擎

索引失效

1.在where子句中进行null值判断的话会导致引擎放弃索引而产生全表扫描
SELECT id FROM table WHERE num is null
在建立数据库的时候因尽量为字段设置默认值,如int类型可以使用0,varchar类型使用 ‘’
当你在指定类型大小如int(11)时,其实空间就已经固定了,即时存的是null也是这个大小

2.避免在where子句中使用!= ,< >这样的符号,否则会导致引擎放弃索引而产生全表扫描
SELECT id FROM table WHERE num != 0

3.避免在where子句中使用or来连接条件,因为如果俩个字段中有一个没有索引的话,引擎会放弃索引而产生全表扫描(注意:要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引)

  1. 避免在where子句中使用int关于网上说的MySQL在使用int不走索引的问题,严谨的来说的话分为俩种情况
    走索引的
    SELECT id FROM table WHERE num IN (1)
    不走索引的
    SELECT id FROM table WHERE num IN (1,2)
    其实在in里面,如果只有一个值的话是等价于num = 1的

  2. 避免在where子句中=的左边使用表达式操作或者函数操作
    表达式

SELECT id FROM table WHERE num / 2 = 1
函数操作
SELECT id FROM table WHERE SUBSTRING(name,1,2) = ‘wise’
避免在where子句中使用like模糊查询( like查询是以%开头)
SELECT id FROM table WHERE name LIKE ‘wise’

6.对于多列索引,不是使用的第一部分(不符合最左前缀原则),则不会使用索引,例子如下:
如果select * from key1=1 and key2= 2;则建立组合索引(key1,key2);
select * from key1 = 1;组合索引有效;
select * from key1 = 1 and key2= 2;组合索引有效;
select * from key2 = 2;组合索引失效;不符合最左前缀原则

  1. 如果列类型是字符串,那一定要在条件中使用引号引起来,否则不会使用索引
    如果mysql估计使用全表扫描比使用索引快,则不使用索引
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值