预编译SQL的缺陷

    众所周知,JDBC的PrepareStatement接口可以进行预编译SQL。这样数据库会将编译后的SQL绑定在这个连接上,只需要不断的进行参数替换就可以提高SQL的执行效率。但是这样的设计是有缺陷的,并不是所有的情况都会提高执行效率,反而也会有最差的情况。

废话不多说。因为数据库的预编译一但创建,执行计划就会一成不变的被保存起来(预编译SQL)。因此,他不可能去适应所有的情况。比如说下面的SQL:

SELECT * FROM USER WHERE LOCATION = '广西'

    假如说,USER表中存储的数据中,“地域”这个字段分配的很广,也就是说他的取值区间平均来说很广。数据库会认为,索引的选择性较好。(PS:何为选择性?假如说性别,一万条数据里只有两种可能,那么他的选择性就不好。因为,索引的B+树只会存在两个结点,数据太过于聚集)所以,这条执行计划就会利用索引。假如说,来自“广西”的USER很少,那么确实取出速度会很快。假如说这条SQL:

SELECT * FROM USER WHERE LOCATION = '上海'

    因为在上海的USER特别多,假如说有上千条记录,那么返回的数据特别多,就回产生很多随机读取。因为,LOCATION不是主键,数据库是按照主键进行聚簇的。这时候,用索引就会相当慢。为什么?

    因为在MYSQL中,如果走索引,就会访问两次硬盘。因为,索引的B+树中存储的DATA并不是表数据的集邮物理位置(RowID),而是主键!他会拿着主键再去磁盘上寻找真实的数据。为什么要这样?因为假如索引有10000个,那么更改主键的话,那么这些数据就不得不搬到合适的物理位置。这样,就会更改10000处!但是并不是所有的数据库都是这么做的,比如ORACLE。ORACLE索引中的数据不仅有主键还有集邮物理位置(RowID),这样做的想法是,住建部可能经常更换。他先拿物理位置(RowID)去取出真实数据,然后和主键比较一下,如果不对再拿主键去取,然后更新中的物理位置(RowID)。这样做的话,就会出现最好情况和最差情况了。

    所以数据量不大的时候,还不如全表扫描来得快。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值