动态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条件中的每个列都加上索引)
-
避免在where子句中使用int关于网上说的MySQL在使用int不走索引的问题,严谨的来说的话分为俩种情况
走索引的
SELECT id FROM table WHERE num IN (1)
不走索引的
SELECT id FROM table WHERE num IN (1,2)
其实在in里面,如果只有一个值的话是等价于num = 1的 -
避免在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;组合索引失效;不符合最左前缀原则
- 如果列类型是字符串,那一定要在条件中使用引号引起来,否则不会使用索引
如果mysql估计使用全表扫描比使用索引快,则不使用索引