对韩峰著《SQL优化最佳实践》P7 案例的质疑
事先申明下,我的DB环境是Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production,如果与作者环境不同而导致结论差异则另当别论。
该案例做了一个id为varchar类型的两种查询对比,我模拟了一下。
我是这样建表的:
create table tb_varchar2id(
id varchar2(20) primary key,
name nvarchar2(20),
sal number(5,0)
) insert into tb_varchar2id
select rownum,dbms_random.string('*',dbms_random.value(6,20)),dbms_random.value(1000,30000) from dual
connect by level<=2000000
order by dbms_random.random
原作中是320万,我机器受限只能弄200万,这个差别不影响作者的思路和我的结论。
建表完提交后,开始第一个查询并观察其执行计划:
SQL> select * from tb_varchar2id where id>='';
已用时间: 00: 00: 00.00 执行计划
----------------------------------------------------------
Plan hash value: 3377844066 -----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1006K| 45M| 3602 (2)| 00:00:44 |
|* 1 | TABLE ACCESS FULL| TB_VARCHAR2ID | 1006K| 45M| 3602 (2)| 00:00:44 |
----------------------------------------------------------------------------------- Predicate Information (identified by operation id):
--------------------------------------------------- 1 - filter("ID">='') Note
-----
- dynamic sampling used for this statement (level=2)
这里走的也是全表扫描,cost是3602,作者那边不同的是8927.
再看封闭范围的查询及执行计划:
SQL> select * from tb_varchar2id where id between '' and '';
已用时间: 00: 00: 00.00 执行计划
----------------------------------------------------------
Plan hash value: 1409398992 ---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 104K| 4773K| 399 (0)| 00:00:05 |
| 1 | TABLE ACCESS BY INDEX ROWID| TB_VARCHAR2ID | 104K| 4773K| 399 (0)| 00:00:05 |
|* 2 | INDEX RANGE SCAN | SYS_C0011453 | 104K| | 357 (0)| 00:00:05 |
--------------------------------------------------------------------------------------------- Predicate Information (identified by operation id):
--------------------------------------------------- 2 - access("ID">='' AND "ID"<='') Note
-----
- dynamic sampling used for this statement (level=2)
这把走的是索引范围扫描,cost是399,原著中是5(作者加了索引SYS_C0025295)。
就本例而言,换了查询方式后cost从3602降到399,似乎有了数量级的提升,而原著中8927到5,更是令人瞠目结舌!
很多看官看到这里都要作者所云以为开放(>=)区间查询要次于封闭区间(between)查询了,还以为作者给出了一条可行的优化之路。
但是,下面两条SQL执行结果是不一样的。
select * from tb_varchar2id where id>='1900000';
select * from tb_varchar2id where id between '1900000' and '2000000';
让我们看看它们的数量:
SQL> set autotrace off;
SQL> select count(*) from tb_varchar2id where id>=''; COUNT(*)
----------
999995 已用时间: 00: 00: 00.21
SQL> select count(*) from tb_varchar2id where id between '' and ''; COUNT(*)
----------
111113 已用时间: 00: 00: 00.00
前者是将近一百万条,后者是十一万条,数据量有一个数量级的差距,cost自然也有一个数量级的差距。
为什么会这样?因为id是varchar2类型,不是number类型,上面SQL在搞字符串比较呢。
就比如运行select * from tb_varchar2id where id>='1900000' and rownum<20;
SQL> select * from tb_varchar2id where id>='' and rownum<20; ID NAME SAL
-------------------- ---------------------------------------- ----------
1900000 YQJQLHKTYVLSZX 12533
1900001 SPLMMLXO 18104
1900002 TYGGIMJCSIWOWUX 6383
1900003 SYYYNRXSL 15890
1900004 GEGQAG 9448
1900005 SFGBZMMPOSEVMNEHQ 20339
1900006 OMQGZZWVEPRWIMTYK 13421
1900007 PWHATEOVY 11135
1900008 TLBRFDWDCEMXFYUXYH 15930
1900009 ZUIQECXIRQXBTO 15961
190001 WKEAMSE 25082 ID NAME SAL
-------------------- ---------------------------------------- ----------
1900010 CMPQCVUBXSMBCMI 17296
1900011 QDPNUNBDXBKV 17393
1900012 OYQBIBRADGE 12009
1900013 VIRWDAKEE 18760
1900014 NQJYHGKREUKGENWH 28990
1900015 IKUUFL 7899
1900016 ACQDSR 1195
1900017 NXIECMAVNE 4208 已选择19行。
连190001都混迹其中,这不应该是符合两个SQL意图的记录。
所以,这是不同SQL在比较性能,这有意义吗?
作者一开头就出这么一个让人费解的地方,或是有些细节没有明写在书里,引起读者疑惑,有点不应该。
--2020年1月31日--
对韩峰著《SQL优化最佳实践》P7 案例的质疑的更多相关文章
- sql优化最佳实践
1.选择最有效率的表连接顺序 首先要明白一点就是SQL 的语法顺序和执行顺序是不一致的 SQL的语法顺序: select [distinct] ....from ....[xxx join][o ...
- SQL Server - 最佳实践 - 参数嗅探问题 转。
文章来自:https://yq.aliyun.com/articles/61767 先说我的问题,最近某个存储过程,暂定名字:sp_a 总是执行超时,sp_a带有一个参数,暂定名为 para1 var ...
- 一触即发 App启动优化最佳实践
一触即发 App启动优化最佳实践 本文在 DiyCode 和 CSDN个人博客 同时首发,关注作者的 DiyCode帐号 或者 作者微博 可第一时间收到新文章推送. 文中的很多图都是Google性能优 ...
- Web前端优化最佳实践及工具集锦
Web前端优化最佳实践及工具集锦 发表于2013-09-23 19:47| 21315次阅读| 来源Googe & Yahoo| 118 条评论| 作者王果 编译 Web优化Google雅虎P ...
- paip.前端加载时间分析之道优化最佳实践
paip.前端加载时间分析之道优化最佳实践 1.另存为 ,查看文件尺寸..和图片. 2.view the 另存为的htm静态的文件单个的加载,看时间...可以排除编程语言的问题and 数据库.. ## ...
- 【读书笔记】读《高性能网站建设指南》及《高性能网站建设进阶指南:Web开发者性能优化最佳实践》
这两本书就一块儿搞了,大多数已经理解,简单做个标记.主要对自己不太了解的地方,做一些记录. 一.读<高性能网站建设指南> 0> 黄金性能法则:只有10%~20%的最终用户响应时间 ...
- [转] Web 前端优化最佳实践之 Mobile(iPhone) 篇
原文链接:http://dbanotes.net/web/best_practices_for_speeding_up_your_web_site_server_mobile.html Web 前端优 ...
- 经典的性能优化最佳实践 web性能权威指南 读书笔记
web性能权威指南 page 203 经典的性能优化最佳实践 无论什么网络,也不管所用网络协议是什么版本,所有应用都应该致力于消除或减 少不必要的网络延迟,将需要传输的数据压缩至最少.这两条标准是经典 ...
- 史上最全存储引擎、索引使用及SQL优化的实践
史上最全存储引擎.索引使用及SQL优化的实践 1 MySQL的体系结构概述 2. 存储引擎 2.1 存储引擎概述 2.2 各种存储引擎特性 2.2.1 InnoDB 2.2.2 MyISAM 3. 优 ...
随机推荐
- 10、Strategy 策略模式 整体地替换算法 行为型模式
1.模式说明 策略模式比较好理解,就是将程序中用到的算法整体的拿出来,并有多个不同版本的算法实现,在程序运行阶段,动态的决定使用哪个算法来解决问题. 2.举例 排序算法的问题,假如我们的程序中需要对数 ...
- 什么才是定制化IDE的核心价值?
写在前面 自 2018 年初,就与 VSCode 结下了不解之缘,从一份选型报告开始,一蹉跎就是 2 年多 期间反复思索着一个挥之不去的问题:定制化 IDE 产品的核心价值是什么? 事实上,答案并不唯 ...
- java_Collection、Map、泛型的使用
Collection集合 集合按照其存储结构可以分为两大类,分别是 单列集合 java.util.Collection 双列集合 java.util.Map Collection:单列集合类的根接口, ...
- JavaScript重定向
使用JavaScript重定向到其他网页的一些方法: location.href location.replace() location.assign() 语法: window.location.hr ...
- 08 vi全屏文本编辑器
打开文件vim /path/to/somefilevim +# :打开文件,并定位于第#行(如下的 vi +33 profile) vim +:打开文件,定位至最后一行vim +/PATTERN : ...
- DB2 SQL Error: SQLCODE=-1585, SQLSTATE=54048
DB2 执行SQL报错: DB2 SQL Error: SQLCODE=-1585, SQLSTATE=54048 你建的db2数据库没有建足够大的临时表空间,新建一个足够大的临时表空间 1.创建数据 ...
- CentOS7(Linux)源码安装MySQL5.7.X
介绍 软件应用最重要的就是数据库了,可是还有小伙伴不会在Linux上安装MySQL数据库,今天就来讲讲如何在CentOS7环境使用源码进行安装MySQL5.7.X. MySQL官网下载链接:https ...
- cvsnt 和wincvs 的安装配置既简单操作 2007-07-28 11:33
CVSNT 配置 版本:CVSNT 2.5.03(Scorpio)Build 2382 安装过程:简单一路next即可. 配置: (一)我们先准备好两个目录,分别是KHRoot,和KHTemp.KHR ...
- jqgrid 自定义文本框、选择框等查询
要实现jqgrid的自定义查询可通过表格获取查询的条件,再给jqgrid表格发送postData参数. HTML: <table id="querytable" border ...
- Spring源码阅读 ------------------- SpringFrameWork 5.2 +IDEA 部署
Spring作为JAVA学习者的必须学习和熟悉的框架,需要理解Spring的设计原理,核心设计模式,对于理解设计模式,面向对象的深入理解有着深远持久的影响,特此首先要做到本地部署源码开始,下面将介绍如 ...