SQL语句性能调整原则

Oracle常见索引扫描方式总结 目录 一、简介 二、索引唯一扫描 三、索引范围扫描 四、索引全扫描 五、索引快速全扫描 六、索引跳跃式扫描 七、总结 一、简介 Oracle提供了五种索引扫描类型,根据具体索引类型、数据分布、约束条件以及where限制的不同进行选择: 索引唯一扫描(index unique scan) 索引范围扫描(index range scan) 索引全扫描(index full scan) 索引快速扫描(index fast full scan) 索引跳跃扫描(index skip s.. 阅读详情
[ 作者: 石骁騑 ]

一、问题的提出
在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用系统提交实际应用后,随着数据库中数据的增加,系统的响应速度就成为目前系统需要解决的最主要的问题之一。系统优化中一个很重要的方面就是SQL语句的优化。对于海量数据,劣质SQL语句和优质SQL语句之间的速度差别可以达到上百倍,可见对于一个系统不是简单地能实现其功能就可,而是要写出高质量的SQL语句,提高系统的可用性。

在多数情况下,Oracle使用索引来更快地遍历表,优化器主要根据定义的索引来提高性能。但是,如果在SQL语句的where子句中写的SQL代码不合理,就会造成优化器删去索引而使用全表扫描,一般就这种SQL语句就是所谓的劣质SQL语句。在编写SQL语句时我们应清楚优化器根据何种原则来删除索引,这有助于写出高性能的SQL语句。

二、SQL语句编写注意问题
下面就某些SQL语句的where子句编写中需要注意的问题作详细介绍。在这些where子句中,即使某些列存在索引,但是由于编写了劣质的SQL,系统在运行该SQL语句时也不能使用该索引,而同样使用全表扫描,这就造成了响应速度的极大降低。

1. IS NULL 与 IS NOT NULL
不能用null作索引,任何包含null值的列都将不会被包含在索引中。即使索引有多列这样的情况下,只要这些列中有一列含有null,该列就会从索引中排除。也就是说如果某列存在空值,即使对该列建索引也不会提高性能。

任何在where子句中使用is null或is not null的语句优化器是不允许使用索引的。

2. 联接列

对于有联接的列,即使最后的联接值为一个静态值,优化器是不会使用索引的。我们一起来看一个例子,假定有一个职工表(employee),对于一个职工的姓和名分成两列存放(FIRST_NAME和LAST_NAME),现在要查询一个叫比尔.克林顿(Bill Cliton)的职工。

下面是一个采用联接查询的SQL语句,

select * from employss
where
first_name||''||last_name ='Beill Cliton'; 

上面这条语句完全可以查询出是否有Bill Cliton这个员工,但是这里需要注意,系统优化器对基于last_name创建的索引没有使用。

当采用下面这种SQL语句的编写,Oracle系统就可以采用基于last_name创建的索引。

Select * from employee
where
first_name ='Beill' and last_name ='Cliton'; 

遇到下面这种情况又如何处理呢?如果一个变量(name)中存放着Bill Cliton这个员工的姓名,对于这种情况我们又如何避免全程遍历,使用索引呢?可以使用一个函数,将变量name中的姓和名分开就可以了,但是有一点需要注意,这个函数是不能作用在索引列上。下面是SQL查询脚本:

select * from employee
where
first_name = SUBSTR('&&name',1,INSTR('&&name',' ')-1)
and
last_name = SUBSTR('&&name',INSTR('&&name’,' ')+1) 

3. 带通配符(%)的like语句

同样以上面的例子来看这种情况。目前的需求是这样的,要求在职工表中查询名字中包含cliton的人。可以采用如下的查询SQL语句:

select * from employee where last_name like '%cliton%'; 

这里由于通配符(%)在搜寻词首出现,所以Oracle系统不使用last_name的索引。在很多情况下可能无法避免这种情况,但是一定要心中有底,通配符如此使用会降低查询速度。然而当通配符出现在字符串其他位置时,优化器就能利用索引。在下面的查询中索引得到了使用:

select * from employee where last_name like 'c%'; 

4. Order by语句

ORDER BY语句决定了Oracle如何将返回的查询结果排序。Order by语句对要排序的列没有什么特别的限制,也可以将函数加入列中(象联接或者附加等)。任何在Order by语句的非索引项或者有计算表达式都将降低查询速度。

仔细检查order by语句以找出非索引项或者表达式,它们会降低性能。解决这个问题的办法就是重写order by语句以使用索引,也可以为所使用的列建立另外一个索引,同时应绝对避免在order by子句中使用表达式。

5. NOT

我们在查询时经常在where子句使用一些逻辑表达式,如大于、小于、等于以及不等于等等,也可以使用and(与)、or(或)以及not(非)。NOT可用来对任何逻辑运算符号取反。下面是一个NOT子句的例子:

... where not (status ='VALID') 

如果要使用NOT,则应在取反的短语前面加上括号,并在短语前面加上NOT运算符。NOT运算符包含在另外一个逻辑运算符中,这就是不等于(<>)运算符。换句话说,即使不在查询where子句中显式地加入NOT词,NOT仍在运算符中,见下例:

... where status <>'INVALID'; 

再看下面这个例子:

select * from employee where salary<>3000; 

对这个查询,可以改写为不使用NOT:

select * from employee where salary<3000 or salary>3000; 

虽然这两种查询的结果一样,但是第二种查询方案会比第一种查询方案更快些。第二种查询允许Oracle对salary列使用索引,而第一种查询则不能使用索引。

6. IN和EXISTS

有时候会将一列和一系列值相比较。最简单的办法就是在where子句中使用子查询。在where子句中可以使用两种格式的子查询。

第一种格式是使用IN操作符:

... where column in(select * from ... where ...); 

第二种格式是使用EXIST操作符:

... where exists (select 'X' from ...where ...); 

我相信绝大多数人会使用第一种格式,因为它比较容易编写,而实际上第二种格式要远比第一种格式的效率高。在Oracle中可以几乎将所有的IN操作符子查询改写为使用EXISTS的子查询。

第二种格式中,子查询以‘select 'X'开始。运用EXISTS子句不管子查询从表中抽取什么数据它只查看where子句。这样优化器就不必遍历整个表而仅根据索引就可完成工作(这里假定在where语句中使用的列存在索引)。相对于IN子句来说,EXISTS使用相连子查询,构造起来要比IN子查询困难一些。

通过使用EXIST,Oracle系统会首先检查主查询,然后运行子查询直到它找到第一个匹配项,这就节省了时间。Oracle系统在执行IN子查询时,首先执行子查询,并将获得的结果列表存放在在一个加了索引的临时表中。在执行子查询之前,系统先将主查询挂起,待子查询执行完毕,存放在临时表中以后再执行主查询。这也就是使用EXISTS比使用IN通常查询速度快的原因。

同时应尽可能使用NOT EXISTS来代替NOT IN,尽管二者都使用了NOT(不能使用索引而降低速度),NOT EXISTS要比NOT IN查询效率更高。
用爬虫搭建自己的行情数据库           我所选择的网址是证券之星,首先想做的第一个函数的功能是爬取 A 股的股票名单和代号。下面的图片是第二页,ranklist_a_3_1_2 中的 2 很显然表示的是第二页,通过一个循环就可以获取所有的 html 内容。         这里使用一个新的库 bs4,用它可以很轻易地把一个 html 对象转化成 xml 对象,也就是一个树状的由很多节点组成结构,我们可以用获取某... 阅读详情

相关推荐

【数据分析/商业分析】面试题整理——SQL专题

数据分析\商业分析—面试题整理 自己总结的SQL类的面试题 文章目录数据分析\商业分析—面试题整理1.新增用户2.活跃用户数量3.连续登录4.次(n)日留存5.每个科目下分数最高的两名学生

awater_17的博客 1833

ZT: 提高SQL性能的措施

提高SQL性能的措施! 最后出处:http://www.ourasp.net/ 作者:石骁騑 收录于:2001年12月19日 一、问题的提出在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用系统提交实际应用后,随着数据库中数据的增加,系统的响应速度就成为目前系统需要解决的最主要的问题之一。系统优化中一个很重要的方

foreveryday007's BLOG 1888

【零基础入门unity游戏开发——3D篇】3D物理关节 —— Joint相关组件

【零基础入门unity游戏开发——3D篇】3D物理关节 —— Joint相关组件

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 1152

Oracle数据库 sql优化

Oracle 数据库sql优化

qq_41128049的博客 1580

oracle查询不走索引全表扫描,使用索引快速全扫描(Index FFS)避免全表扫描的若干场景-Oracle...

使用索引快速全扫描(Index FFS)避免全表扫描的若干场景什么使用使用Index FFS比FTS好?Oracle 8的Concept手册中介绍:1. 索引必须包含所有查询中参考到的列。2. Index FFS只能通过CBO(Index hint强制使用CBO)获得。3. Index FFS使用hint:/*+ INDEX_FFS() */。Index FFS是在7.3中引入的。在Oracle ...

weixin_35458961的博客 1196

数据库SQL优化大总结之 百万级数据库优化方案

网上关于SQL优化的教程很多,但是比较杂乱。近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充。 这篇文章我花费了大量的时间查找资料、修改、排版,希望大家阅读之后,感觉好的话推荐给更多的人,让更多的人看到、纠正以及补充。   1.对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。 2.应尽量避免在 w

帅性而为1号的博客 15万+

股票数据Scrapy爬虫

功能描述 • 目标:获取上证A股股票名称和交易信息 • 输出:保存到文件中 • 技术路线:采用scrapy框架进行爬取 此处选取股票信息静态存储在HTML页面中的页面进行爬取,之后会写一篇动态的爬取方式 程序结构设计 (1)首先得到股票代码,此处选取证券之星获得上证A股股票代码 (2)根据股票代码到网易财经获取个股详细信息 (3)将结果存储到文件 代码实现 此处在spiders文件下新创建了一个stocks.py文件 stocks.py # -*- coding: utf-8 -*- import re i

Slatter的博客 1248

python爬虫基础class 3(爬取京东商品姓名和爬取股票信息)

# 京东笔记本 import requests import re import bs4 num = 0 def getHtmlText(url): try: hd = {'user-agent': 'Mozilla/5.0'} r = requests.get(url, headers=hd, timeout=...

aaakirito的博客 617

MTK 手机开发小技巧(2)(3)

http://blog.csdn.net/jiangyu912/article/details/5721672 声明:本资料归本公司同事整理提供 修改默认输入法 方法1: common_mmi_cache_config.c   NVRAM_SETTING_PREFER_INPUT_METHOD 默认值   延伸: common_mmi_cache_byte 默认语言:NVR

Gabby 1677

MTK 手机开发小技巧(2)

<br />   声明:本资料为公司同事整理提供<br /><br /> <br />MMICheckDiskDisplay            开机点亮背光<br /> <br />PEN_CHECK_BOUND              检查触笔位置是否在控制区域<br />wgui_general_pen_down_hdlr   触屏事件<br /> <br />setup_dialing_keypad  拨号界面<br />gui_dialing_key_select  显示选中拨号图片<br /

爱上晴天的雨 2844

MTK的一些笔记

<br /><br />MMICheckDiskDisplay            开机点亮背光<br />PEN_CHECK_BOUND              检查触笔位置是否在控制区域<br />wgui_general_pen_down_hdlr   触屏事件<br />setup_dialing_keypad  拨号界面 <br />gui_dialing_key_select  显示选中拨号图片<br />ExecuteDialKeyPadKeyHandler<br />gui_dialin

crane 1455

MTK散记1(转)

MMICheckDiskDisplay               开机点亮背光PEN_CHECK_BOUND              检查触笔位置是否在控制区域wgui_general_pen_down_hdlr   触屏事件setup_dialing_keypad  拨号界面 gui_dialing_key_select  显示选中拨号图片ExecuteDialKeyPa

zhoulianghao166的专栏 1770

题: 计算机网络常见故障 网络收集的

 ASDL断流问题  问:我最近安装了ADSL宽带,但是上网的时候数据流传输突然中断,没有反应,过一阵子又自动恢复正常,表现为网页打不开,下载中断,在线收看或收听的视频或音频中断。对于这一情况,电信的ADSL检修人员也无能为力。请龙哥帮我,谢谢。   答:用过56K Modem的用户大都有

1452

来自火山引擎的 MCP 安全授权新范式

本文旨在深入剖析火山引擎 Model Context Protocol (MCP) 开放生态下的 OAuth 授权安全挑战,并系统阐述火山引擎为此构建的多层次、纵深防御安全方案。面对由 OAuth 2.0 动态客户端注册带来的灵活性与潜在风险,我们设计了从“事前防御”到“事中限制”,再到“事后兜底”的完整安全闭环。

volcenginetod的博客 1108

MTK的一些笔记【转】

<br />MMICheckDiskDisplay            开机点亮背光 <br />PEN_CHECK_BOUND              检查触笔位置是否在控制区域<br /> wgui_general_pen_down_hdlr   触屏事件<br />setup_dialing_keypad  拨号界面 <br /> gui_dialing_key_select  显示选中拨号图片<br /> ExecuteDialKeyPadKeyHandler<br /> gui_di

陈云峰技术博客 1898

中国国产浏览器有哪些

国产浏览器 web browser

贺浦力特的博客 6872

IT风投

概念风投 风险投资是由职业金融家投入到新兴的、迅速发展的、具有巨大竞争潜力的企业中一种权益资本。从投资行为的角度来讲,风险投资是把资本投向蕴藏着失败风险的高新技术及其产品的研究开发领域,旨在促使高新技术成果尽快商品化、产业化,以取得高资本收益的一种投资过程。. 风投在IT领域: 2004年至2017年中国IT领域风投不断向前发展,出现了许多问题,解决了许多难题,不断改变投资和退出形式,顺应经

zjw819703057的博客 469

PowerShell7.5.1

PowerShell7.5.1

上一篇: 如果你想设计一个数据库管理系统,看看这里
下一篇: 理解与掌握ACCESS--经验谈
亮小小猪
博客等级 码龄22年 23粉丝 60原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值