sql 分页_MySQL 隐式转换与分页查询的SQL优化

在介绍之前,先看一下我们的示例表,建表语句如下:

eca717c37bb9ed02a2ef100520986a9a.png

隐式转换

当我们对不同类型的值进行比较的时候,为了使得这些数值可比较,MySQL会做一些隐式转化(Implicit type conversion)。

SQL查询语句的条件中字段赋值与字段定义类型不匹配是一种常见的错误用法。

e27fedcdda7cd520617446df3e7799d7.png

如上,字段account的定义为varchar,在WHERE 条件中,account字段类型与条件赋值两者数据类型不一样,这时是没法直接进行比较的,需要进行类型转换。MySQL的策略是将表中字段全部转换为整型之后再比较,由于函数作用于表字段,引起索引失效,导致全表扫描,正确的写法如下:

4b7253a81decf169bfdf7b36db162b69.png

由隐式类型转换引入的安全问题

隐式类型转换不仅可能引起性能问题,还有可能产生安全问题。加入前端没有WAF防护,那么下面的sql是很容易被注入的。

c9f79dd5e67e66fbea91807b5c260cc9.png

此时登录页面username输入 OR 1='1 ,password随便输入,这样就生成了下面的查询,有可能登录系统:

99dabf819656785688f6074f52c820cd.png

关于官方的隐试转换说明

  • 两个参数至少有一个是 NULL 时,比较的结果也是 NULL,例外是使用 <=> 对两个 NULL 做比较时会返回 1,这两种情况都不需要做类型转换。
  • 两个参数都是字符串,会按照字符串来比较,不做类型转换。
  • 两个参数都是整数,按照整数来比较,不做类型转换。
  • 十六进制的值和非数字做比较时,会被当做二进制串。
  • 有一个参数是 TIMESTAMP 或 DATETIME,并且另外一个参数是常量,常量会被转换为 timestamp。
  • 有一个参数是 decimal 类型,如果另外一个参数是 decimal 或者整数,会将整数转换为 decimal 后进行比较,如果另外一个参数是浮点数,则会把 decimal 转换为浮点数进行比较。
  • 所有其他情况下,两个参数都会被转换为浮点数再进行比较。


LIMIT 分页

分页查询在我们的实际应用中非常普遍,也是最容易出问题的查询场景。比如对于下面简单的语句,一般想到的办法是在name,age,register_time字段上创建复合索引。这样查询条件排序可以有效的利用复合索引,提升查询性能。

1a595a8b3feff67939c0f2626d5bbb42.png

如上例子,当 LIMIT 子句变成 “LIMIT 100000, 50” 时,此时我们会发现,只取50条语句为何会这么慢?

原因很简单,MySQL并不知道第100000条记录从什么地方开始,即使有索引也需要从头计算一次,因此会感觉非常的慢,一般我们在做翻页时,是可以获取上一页中的某个数据标志来缩小查询范围的,比如时间,可以将上一页的最大值时间作为查询条件的一部分,SQL可以优化为这样:

d18bd90b40c1c941e68a415facedb39e.png

08c78ee4243456d9e772f119fb67e14b.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值