??xml version="1.0" encoding="utf-8" standalone="yes"?>
==============================实践?==============================
如果两个字段都是DATE型,那么直接用END_DATE - BEGIN_DATE卛_Q不需要Q何{型,取整直接用TRUNC卛_QTRUNC(END_DATE - BEGIN_DATE),q样是直接将数部分舍去?/p>
=====================================================================
*************实例Q包括MONTHS_BETWEEN,ADD_MONTHS,MOD,LAST_DAY的用法)******************
/*
解决ҎQ本例假讄L?007Q?5月䆾的报告及时率
1.需要要取得2007Q?5月䆾需要做随访的婴儿信?br> 2.再查询出q些婴儿中在本次随访中已l做了随访ƈ且满?lt;=20天的
*/
/*2007Q?月需要随访的婴儿ID*/
select T.ID,T.* /*不太准确*/
from fy_new_baby t
where
mod(trunc(months_between(TO_DATE('2007-05-31', 'yyyy-mm-dd') ,t.birthday)),12) in (1,3,6,9,12)
and t.live = '1'
select T.ID,T.* /*比较准确*/
FROM FY_NEW_BABY T
WHERE MOD(TRUNC(MONTHS_BETWEEN(TO_DATE('2007-05-31','yyyy-mm-dd'),T.BIRTHDAY)),12) IN (1,3,6,9,12)
AND T.LIVE = '1'
/*本月需要做随访的ƈ且已l做了随访的记录
Q其中也包括了以前做q随访而ƈ非算是本ơ随访的Q后面通过Q随访日期-本次应该随访日期Q?gt;0来将其排除掉*/
select v.* from fy_register_visit v
where v.new_baby_id in (select T.ID
from fy_new_baby t
where
mod(trunc(months_between(TO_DATE('2007-05-31', 'yyyy-mm-dd') ,t.birthday)),12) in (1,3,6,9,12)
and t.live = '1')
/*出生日期和本月的月差*/
SELECT MONTHS_BETWEEN(TO_DATE('2007-05-31','YYYY-MM-DD'),T.BIRTHDAY) FROM FY_NEW_BABY T
/*本月需要做随访的婴儿在本月应该随访的日?/
select T.ID,T.BIRTHDAY,ADD_MONTHS(T.BIRTHDAY,TRUNC(MONTHS_BETWEEN(TO_DATE('2007-05-31','YYYY-MM-DD'),T.BIRTHDAY)) ),t.*
from fy_new_baby t WHERE T.ID IN (select T.ID
from fy_new_baby t
where
mod(trunc(months_between(TO_DATE('2007-05-31', 'yyyy-mm-dd') ,t.birthday)),12) in (1,3,6,9,12)
and t.live = '1')
/*需要在本月做随访的婴儿的随访日期-本月应该做随访的日期*/
select ff.id,v.vst_date,ff.birthday, ff.shouldvisit,(v.vst_date-ff.shouldvisit) as day from fy_register_visit v,
( select T.ID as id,T.BIRTHDAY as birthday,ADD_MONTHS(T.BIRTHDAY,TRUNC(MONTHS_BETWEEN(TO_DATE('2007-05-31','YYYY-MM-DD'),T.BIRTHDAY)) ) as shouldvisit
from fy_new_baby t WHERE T.ID IN (select T.ID
from fy_new_baby t
where
mod(trunc(months_between(TO_DATE('2007-05-31', 'yyyy-mm-dd') ,t.birthday)),12) in (1,3,6,9,12)
and t.live = '1') ) ff
where v.new_baby_id = ff.id
/*随访表中满Q随访日期-本月应该随访日期<=20Q的*/
select ff.id,v.vst_date,v.vst_zonecode,ff.birthday, ff.shouldvisit,(v.vst_date-ff.shouldvisit) as day from fy_register_visit v,
( select T.ID as id,T.BIRTHDAY as birthday,ADD_MONTHS(T.BIRTHDAY,TRUNC(MONTHS_BETWEEN(TO_DATE('2007-05-31','YYYY-MM-DD'),T.BIRTHDAY)) ) as shouldvisit
from fy_new_baby t WHERE T.ID IN (select T.ID
from fy_new_baby t
where
mod(trunc(months_between(TO_DATE('2007-05-31', 'yyyy-mm-dd') ,t.birthday)),12) in (1,3,6,9,12)
and t.live = '1') ) ff
where v.new_baby_id = ff.id
and v.vst_date-ff.shouldvisit<=20
and v.vst_date-ff.shouldvisit>=0
/*2007-05月䆾需要随访的zM婴儿L---按地区分l?br> 因ؓFY_NEW_BABY表中没有地区字段Q所以需要关联FY_PREGNANT_REG?/
select B.REP_ZONECODE , count(*) as shouldVisitNum
FROM FY_NEW_BABY T,FY_PREGNANT_REG B
WHERE MOD(TRUNC(MONTHS_BETWEEN(TO_DATE('2007-05-31','yyyy-mm-dd'),T.BIRTHDAY)),12) IN (1,3,6,9,12)
AND T.LIVE = '1'
AND T.CARD_ID = B.ID
GROUP BY B.REP_ZONECODE
/*2007Q?5月䆾需要随访的婴儿q且已经存在在随访表中ƈ满Q?=<随访日期Q本月应该随访日?lt;=20Q的*/
select v.vst_zonecode, count(distinct v.id) as visitNum /*ff.id,v.vst_date,ff.birthday, ff.shouldvisit,(v.vst_date-ff.shouldvisit) as day*/
from fy_register_visit v,
(select T.ID as id,
T.BIRTHDAY as birthday,
ADD_MONTHS(T.BIRTHDAY,
TRUNC(MONTHS_BETWEEN(TO_DATE('2007-05-31',
'YYYY-MM-DD'),
T.BIRTHDAY))) as shouldvisit
from fy_new_baby t
WHERE T.ID IN (select T.ID
from fy_new_baby t
where mod(trunc(months_between(TO_DATE('2007-05-31',
'yyyy-mm-dd'),
t.birthday)),
12) in (1, 3, 6, 9, 12)
and t.live = '1')) ff
where v.new_baby_id = ff.id
and v.vst_date - ff.shouldvisit <= 20
and v.vst_date - ff.shouldvisit >= 0
group by v.vst_zonecode
***************************************用例END****************************************
===========================参考资?===============================================
Oracle中如何计时间差
计算旉差是Oracle DATA数据cd的一个常见问题。Oracle支持日期计算Q你可以创徏诸如“日期1Q日?”q样的表辑ּ来计这两个日期之间的时间差?/p>
一旦你发现了时间差异,你可以用简单的技巧来以天、小时、分钟或者秒为单位来计算旉差。ؓ了得到数据差Q你必须选择合适的旉度量单位Q这样就可以q行数据格式隐藏?/p>
使用完善复杂的{换函数来转换日期是一个诱惑,但是你会发现q不是最好的解决Ҏ?/p>
round(to_number(end-date-start_date))- 消逝的旉Q以天ؓ单位Q?/p>
round(to_number(end-date-start_date)*24)- 消逝的旉Q以时为单位)
round(to_number(end-date-start_date)*1440)- 消逝的旉Q以分钟为单位)
昄旉差的默认模式是什么?Z扑ֈq个问题的答案,让我们进行一个简单的SQL *Plus查询?/p>
SQL> select sysdate-(sysdate-3) from dual;
SYSDATE-(SYSDATE-3)
-------------------
3
q里Q我们看COracle使用天来作ؓ消逝时间的单位Q所以我们可以很Ҏ的用{换函数来把它转换成小时或者分钟。然而,当分钟数不是一个整数时Q我们就会遇到放|小数点的问题?/p>
Select
(sysdate-(sysdate-3.111))*1440
from
dual;
(SYSDATE-(SYSDATE-3.111))*1440
------------------------------
4479.83333
当然Q我们可以用ROUND函数Q即取整函数Q来解决q个问题Q但是要C我们必须首先把DATE数据cd转换成NUMBER数据cd?/p>
Select
round(to_number(sysdate-(sysdate-3.111))*1440)
from
dual;
ROUND(TO_NUMBER(SYSDATE-(SYSDATE-3.111))*1440)
----------------------------------------------
4480
我们可以用这些函数把一个消逝时间近D{换成分钟q把q个值写入Oracle表格中。在q个例子里,我们有一个离U(logoffQ系l触发机制来计已l开始的会话旉q把它放入一个Oracle STATSPACK USER_LOG扩展表格之中?/p>
Update
perfstat.stats$user_log
set
elapsed_minutes =
round(to_number(logoff_time-logon_time)*1440)
where
user = user_id
and
elapsed_minutes is NULL;
功能Q?/span>Oracle数据导入导出imp/expq当与oracle数据q原与备份?/span>
大多情况都可以用Oracle数据导入导出完成数据的备份和q原Q不会造成数据的丢失)?/span>
Oracle有个好处Q虽然你的电脑不是服务器Q但是你装了oracle客户端,q徏立了q接
Q通过net8 assistant中本?/span>-->服务命名 d正确的服务命?/span>
其实你可以想成是客户端与服务器端修了条\Q然后数据就可以被拉q来了)
q样你可以把数据导出到本圎ͼ虽然可能服务器离你很q?/span>
你同样可以把dmp文g从本地导入到q处的数据库服务器中?/span>
利用q个功能你可以构Z个相同的数据库,一个用来测试,一个用来正式用?/span>
执行环境Q可以在SQLPLUS.EXE或?/span>DOSQ命令行Q中执行Q?/span>
DOS中可以执行时׃ ?/span>oracle 8i ?/span> 安装目录\ora81\BIN被设|ؓ全局路径Q?/span>
该目录下?/span>EXP.EXE?/span>IMP.EXE文g被用来执行导入导出?/span>
oracle?/span>java~写Q我?/span>SQLPLUS.EXE?/span>EXP.EXE?/span>IMP.EXEq俩个文件是被包装后的类文g?/span>
SQLPLUS.EXE调用EXP.EXE?/span>IMP.EXE他们所包裹的类Q完成导入导出功能?/span>
下面介绍的是导入导出的实例,向导入导出看实例基本上就可以完成Q因为导入导出很单?/span>
数据导出Q?/span>
1 数据库TEST完全导出,用户?/span>system 密码manager 导出?/span>D:\daochu.dmp?/span>
exp system/manager@TEST file=d:\daochu.dmp full=y
2 数据库?/span>system用户?/span>sys用户的表导出
exp system/manager@TEST file=d:\daochu.dmp owner=(system,sys)
3 数据库中的?/span>table1 ?/span>table2导出
exp system/manager@TEST file=d:\daochu.dmp tables=(table1,table2)
4 数据库中的?/span>table1中的字段filed1?/span>"00"打头的数据导?/span>
exp system/manager@TEST file=d:\daochu.dmp tables=(table1) query=\" where filed1 like '00%'\"
上面是常用的导出Q对于压~我不太在意Q用winzip?/span>dmp文g可以很好的压~?/span>
不过在上面命令后?/span> 加上 compress=y 可以了
数据的导?/span>
1 ?/span>D:\daochu.dmp 中的数据导入 TEST数据库中?/span>
imp system/manager@TEST file=d:\daochu.dmp
上面可能有点问题Q因为有的表已经存在Q然后它报错,对该表就不进行导入?/span>
在后面加?/span> ignore=y 可以了?/span>
2 ?/span>d:\daochu.dmp中的?/span>table1 导入
imp system/manager@TEST file=d:\daochu.dmp tables=(table1)
基本上上面的导入导出够用了。不情冉|是将表彻底删除,然后导入?/span>
注意Q?/span>
你要有够的权限Q权限不够它会提CZ?/span>
数据库时可以q上的。可以用tnsping TEST 来获得数据库TEST能否q上?/span>
可以通过输入 IMP 命o和您的用户名/口o
后接用户?/span>/口o的命?/span>:
例程: IMP SCOTT/TIGER
或?/span>, 可以通过输入 IMP 命o和各U参数来控制“导入”
按照不同参数。要指定参数Q您可以使用关键?/span>:
格式: IMP KEYWORD=value ?/span> KEYWORD=(value1,value2,...,vlaueN)
例程: IMP SCOTT/TIGER IGNORE=Y TABLES=(EMP,DEPT) FULL=N
?/span> TABLES=(T1: P1,T1: P2)Q如?/span> T1 是分
USERID 必须是命令行中的W一个参数?/span>
关键?/span> 说明Q默认) 关键?/span> 说明Q默认)
--------------------------------------------------------------------------
USERID 用户?/span>/口o FULL 导入整个文g (N)
BUFFER 数据~冲区大?/span> FROMUSER 所有h用户名列?/span>
FILE 输入文g (EXPDAT.DMP) TOUSER 用户名列?/span>
SHOW 只列出文件内?/span> (N) TABLES 表名列表
IGNORE 忽略创徏错误 (N) RECORDLENGTH IO 记录的长?/span>
GRANTS 导入权限 (Y) INCTYPE 增量导入cd
INDEXES 导入索引 (Y) COMMIT 提交数组插入 (N)
ROWS 导入数据?/span> (Y) PARFILE 参数文g?/span>
LOG 屏幕输出的日志文?/span> CONSTRAINTS 导入限制 (Y)
DESTROY 覆盖表空间数据文?/span> (N)
INDEXFILE 表/索引信息写入指定的文?/span>
SKIP_UNUSABLE_INDEXES 跌不可用烦引的l护 (N)
FEEDBACK ?/span> x 行显C?/span> (0)
TOID_NOVALIDATE 跌指定cd ID 的验?/span>
FILESIZE 每个转储文g的最大大?/span>
STATISTICS 始终导入预计的l计信息
RESUMABLE 遇到与空格有关的错误时挂?/span> (N)
RESUMABLE_NAME 用来标识可恢复语句的文本字符?/span>
RESUMABLE_TIMEOUT RESUMABLE 的等待时?/span>
COMPILE ~译q程, E序包和函数 (Y)
下列关键字仅用于可传输的表空?/span>
TRANSPORT_TABLESPACE 导入可传输的表空间元数据 (N)
TABLESPACES 要传输到数据库的表I间
DATAFILES 要传输到数据库的数据文?/span>
TTS_OWNERS 拥有可传输表I间集中数据的用?/span>
已有的PDM文g到成rtf文gQ?br>1Q?br>打开已有的PDM文gQ》然后选中根目录-》在菜单栏中选择“Model”Q?#8220;Reports”Q?#8220;Manage Templates”Q?#8220;List of Report Templates”中选择“Standard Physical Reprot”Q》点M面菜单栏中的新徏Q》选择最下面?#8220;Physical Data Model”Qƈ填写Name,语言选择chinese,点击OKQ》弹?#8220;Available items”?#8220;Template items”界面Q》在左面的列表中选择“Table”->"Table Column list"->双击Q将光择到右面的目中-》展开Table树型Q右键点击Table Column listQ》选择Layout属性,开在此界面中选择要导出的rtf中的列-》退出右键点击Table Colum list选择“edit”Q》在此设|导出的表名Q可设中?PARENT%及英文名%PARENTCODE%Q点M面的insertQ,点击OK?/p>
Toad快速入?/b>
www.InnovateDigital.com 整理
在Oracle 应用E序的开发过E中Q访问数据库对象和编写SQLE序是一件乏味且耗费旉的工作,Ҏ据库q行日常理也是需要很多SQL脚本才能完成的。Quest Software为此提供了高效的Oracle应用开发工?ToadQTools of Oracle Application DevelopersQ。在Toad的新版本中,q加入了DBA模块Q可以帮助DBA完成许多日常理工作。它最大的特点是单易用,讉K速度快。?ToadQ我们可以通过一个图形化的用L面快速访问数据库Q完成复杂的SQL和PL/SQL代码~辑和测试工作。Toad由Oracle开发专家专门ؓ开发h员而设计,是一个功能强大、结构紧凑的专业化PL/SQL开发环境?/font>
Toad 主要h如下特点Q?/font>
模式览功能可以让我们快速访问数据字典,览数据库中的表、烦引、存储过E。Toad 提供Ҏ据库的快速访问,使用极ؓ方便Q用L面简z,l构安排合理。当我们点击一个单独的数据库对象,Toad立即昄此对象的详细信息。例如,当我们点一个数据库的表Q所有和此表相关的烦引、约束、存储过E、SQL语句以及和其他表的相互引用关p都在同一界面昄出来。ؓ了简化操作,用户可以在浏览窗口操作数据库对象?/font>
SQL ~辑器的主要功能是编辑、运行和调整SQL语句。TOAD 的高U编辑窗口包括众多的Ҏ来提高开发h员编写SQL语句的品化E度。例如,单地生成代码模板Q在~写SQL前自动发现包的内容和列的名字{等?/font>
SQL ~辑器包括一个编辑窗口和q行l果H口Q允许开发h员在~辑的过E中试q行l果。SQL~辑器中不仅包括标准的编辑命令,也包括一些增强的功能Q如快速查询表中的字段、将SQL语句的内Ҏ式化{等。这个窗口可以处理大?GB 的内容,对大的开发项目来说非常有用。便L书签可以让开发h员非常容易地扑ֈ相关位置。在q行l果H口可提供用户定义的配置功能Q支持LONG 和LONG RAW列,可以数据卸出到盘、打印数据、编辑数据等{?/font>
存储q程~辑器的主要功能是编辑、编译、测试、调试存储过E和触发器。TOAD提供语法标识、错误标识和其他很多易于使用的功能,如在弹出H口昄表名、列名和Oracle函数。和其他?PL/SQL ~辑工具不同QTOAD 允许在一个文件中操作多个数据库对象,可以~译一个对象、编译多个对象、编译到当前光标、从光标开始编译。在q行出现错误Ӟ存储q程停止到有问题的语句。用户可以用快h式或模板来快速编写PL/SQL,也可以根据需要生成自q模板。用Toad可以非常方便地进行编辑工作,可如讄书签、取消注释、格式化SQL语句{等?/font>
Toad 提供单易用的PL/SQL 调试功能Q可以节省开发h员在大型目中用于开发和试的宝贉|_提高应用开发的质量。在存储q程开发的q程中,Toad可以逐行~辑、调试和q行代码。运行时可以Ҏ需要输入参敎ͼ观察相关参数的变化来查存储过E的正确性。在调式q程中,Toad 可以通过H口昄所有的断点、参? 调用堆栈和输出参数。用ToadQ非常容易检到存储q程的错误,开发h员可以一步一步运行PL/SQL语句来识别问题。调试会话可以和其他E序会话同时q行?/font>
帮助开发h员优化SQLQؓ他们提供各种优化模式下SQL执行计划Qƈ且能够给Z化的Q能够比较各U模式下实际的SQLq行l果Q帮助开发h员真正高速地开发高效地代码?/font>
Toad q可以外挂一些别的品,比如PL/Formatter, RevealNet Knowledge Base , SQL Impact{,q些都能够和Toad紧密集成Q共同提供了一个完的集成开发环境。新版本q新增加了DBA模块Q更加拓q了Toadq个产品的适用范围?/font>
客户端:
服务器端Q?/font>
1Q?三种安装方式的选择Q?/font>
a) TOAD and Personal Configuration Files to PC 默认安装选择Q完成一个完整的Client端的安装Q把所有需要的文g拯到本地Toad目录。绝大多数用户应该选择使用q个安装方式?
b) Personal Config Files to PC, read TOAD from Network Server 从网l服务器dToadE序Q在本地计算机安装一些自定义的文Ӟq且创徏到服务器文g的快h式,一般不推荐使用q个方式Q而且要求|络服务器已l配|?
c) TOAD to Network Server
把Toad安装到网l服务器上,以便q样别的用户能够q行Personal Config Files to PC, read TOAD from Network Serverq种方式的安装?/font>
2Q?Ҏ需要用到的特性,需要运行一些脚?都在Toad\temps目录?
Schema browser是Toad的极为有特色的模块。在schema browser的帮助下Q可以方便的览数据库内部的各类数据库对象,比如表,索引Q序列,存储q程{,而且可以方便的倒出DDL语句和进行各U修改,重徏工作。定位到某一cd象上Q这列对象允许的操作都会自动列出来?/font>
特色Q?/font>
调试步骤具体举例Q?/font>
1Q?点击菜单栏的W三个按钮: 打开Procedure Editor
2Q?点击Procedure Editor的菜单栏?按钮Q调出需要调试的存储q程
3Q?单击工具栏上的按?Q输入需要传入的参数Q如果不需要传入参敎ͼ可以直接单击工具栏上的按钮: Q直接开始调试,如下图输入传入参敎ͼ
4Q?单击菜单栏的按钮Q?Q可以单步跟t,也可以定义一个断点,直接q行到断点在单步执行Q在存储q程q行的过E中Q当前语句会高亮度显C,q且把鼠标指针定位到变量上,Toad自动昄该变量的当前倹{?/font>
5Q?可以随时中止E序的执行,只要点Debug ->Halt ExecutionQ或者菜单栏上的按钮 Q就可以中止E序的执?/font>
6Q?当碰C个存储过E调用另外一个存储过E的时候,可以选择跌(Step Over) Q这样就直接q行那个被调用的存储q程Q返回调用结果,l箋q个存储q程的调试,也可以选择Trace Into Q这样就打开被调用的存储q程Q进一步深入调试那个被调用的子存储q程。如果需要保持Debug信息Q在~译的时候应该选择Compile Dependencies with Debug InformationQ就是Procedure Editor工具栏最双的那个按??/font>
7Q?支持对变量实时追t:使用WatchQ可以在q行前,或者运行过E中Ҏ个变量进行实时跟t:Add WatchQ把鼠标定位到该变量上,然后点击Debug ->Add Watch At CursorQ该变量׃出现在Debug状态窗口上Q而且实时反应该变量的当前倹{如上图中的变量v_empname。可以运行时M?
8Q?断点支持Q单d储过E需要加断点的地方的行号Q该行颜色变U,输入参数Q单L行按?Q可以直接运行到断点处,可以不必逐行q踪Q更加高效率的进行调试?
Debug Optionq支持条件断点,只有当满x件的时候才会在那个地方停止Q否则就好像不存在这个断点一Ll运行?/font>
注意DBMS_OUTPUT.PUT_LINE的结果只有当E序执行完成以后才会出现Q在E序执行q程中是没有l果的?/font>
我们知道QOralce数据库的优化Q最主要的步骤就在于SQL的优化。而在没有专门的工P如ToadQ的帮助下,q行SQL优化是一仉常困隑֒乏味的事情,q且需要对Oracle的深入理解和高超的Oracle调优技巧。用Toad的SQLab Xpert Tuning模块Q可以我们普通开发h员也能够非常快速,_的对SQLq行专家U的分析
在SQL Editor和Procedure Editor里面Q选中需要调试的SQL语句QSQLab Xpert只能调试Select,Insert, Update,Delete语句Q,复制到SQL Editor里面Q然后点dh上的调优按钮 QToad会自动打开SQLab xpert H口Q捕获当前的SQL语句Qƈ且把它{化ؓW合explain plan格式的语句?/font>
W一ơ打开Xpert的时候,Toad会提CZQ需要安装一些Server端的表、视囑֒包等对象Q可以把表存储到某个指定的表I间(如Tools)里面。可以简单的按照提示一步一步做可以了。如果系l设定不允许Job的话QJob_queue_process=0Q?Toad提示有些部g不会现在安装Q可以忽略。安装完成以后,可以选择让某些非DBA用户也可以用Toad的SQLab Xpert调优功能?/font>
安装完成以后QToad会提CZ一些关于优化目标方面的问题Q你可以选择每次优化都可以重新设定,或者一ơ设定,以后一直用这个设定。当然如果需要,q是可以更改的,在SQLab Option xpert的窗口的Administration和Preference下面重新讑֮?/font>
例子Q?/font>
下面q个SQL语句涉及到多表之间的兌Q有一定的复杂性,我们可以借助Toad的SQLab Xpert Option来帮助分析:
select a.name. b.name, c.emp_name from dep a, manager b,emp c where a.dep_no=c.DEP_NO and b.manag_id=c.manag_id and c.emp_no=3
我们把这个SQL复制到SQL Editor里面Q单M面的调优按钮QToad打开SQLab Xpert OptionH口?/font>
从上面的图中我们可以斚w的看刎ͼ在各U优化模式下Q该SQL语句的执行计划分别是什么样的,Toadl出了每一U执行计划的具体每一个步骤,每个步骤的成本,该表涉及的相关的数据{,如果SQL存取的表q没有经q分析,Toad会以U色警告昄Qƈ且很方便的帮助你对该表进行分析,攉l计数据Q重建烦引等Q以有助于优化器作出最好的选择。可以把当前的分析结果保存到它的资料库里边,以备以后再次调用之需?/font>
我们q可以求助与SQLab 的自动优化功能:点击Original SQL下面的auto tune按钮QToad会对执行l果按照tkprofq行分析Q当Ӟq需要你在initsid.ora里面讄好utl_file_dirQ如果服务器是在Unix机器上的话,q需要通过FTP方式得到Trace文gQ有一些小的讄Q?/font>
自动优化非常高效的对所有执行计划进行实际运行比较,q且l出实际执行的时间的ҎQ如下图Q?/font>
我们q可以让Toadl出实际的优化徏议:点击Original SQL,单击下面的Advice按钮QToadҎ对SQL的分析和执行l果l出合理的徏议:
1Q?把表和烦引分别放C个不同的表空_因ؓ我们在创Q加上约束的时候没有指定USING INDEX子句Q所以表和烦引都建立在了用户的默认表I间上了?/font>
2Q?对表EMPQDEP和MANAGERq行分析Q收集最新的l计数据Q有利于CBO得到最优的执行计划
3Q?在合适的列上创徏索引QEMP的manag_id和dep_no。当表中存在大量的数据的时候,q样可以大大减少׃全表扫描带来的成本?/font>
SQL Modeler可以帮助开发h员很Ҏ的写出各U复杂的SQL语句Q只需通过单的拖动鼠标Q就能够写出复杂的SQL语句来?/font>
打开SQL Modeler的几个途径Q?/font>
H口׃个主要部分组成: 在SQL Modeler里面Q还支持对生成的SQLq行Explain PlanQ调试SQL的性能Q运行SQLQ看是否得到了希望的l果Q保存生成的语句Q或者把语句_脓到SQL Editor里面?/font> 有了SQL Modeler的帮助,即是初U的E序员也能编写出复杂而又高效的SQL查询来。比如下面的例子 生成步骤Q?/font> 1Q?选出表emp, dep, manager 2Q?用鼠标拖住emp的emp_name和emp_no, dep的name,manager的name 3Q?双击criteriaH口的emp_no condition列,弹出H口Q输入查询条Ӟ比如emp_no=3 4Q?׃l果里面不希望emp_no出现Q双击emp_no列的visibleQ设|ؓfalse 5Q?q样出来了需要的查询Q现在可以运行查询得到结果,Ҏ询SQLq行分析Q或者在SQL Editor里面打开q个SQLQ或者保存ؓSQL Model文gQ或者再q一步处理,比如加排序, 汇ȝ?/font> DBA斚w的功能: Toad在DBA日常理斚w的能力是非常强大的,可以帮助DBA安全快速地完成许多日常工作Q还有ToadҎ的一些小工具能完成一些普通方法很隑ց到的功能。下面大概讲qC各个常用模块的主要功能: a) Database Monitor 提供直观的Oracle数据库运行状况,包括下面q些详细信息Q可以看到逻辑IOQ物理IOQ各个状态的session数目QSGA的利用率Q共享池的用状况,各类事g的等待状况,以及各类事g随着旉的变化情?/font> b) Instance Monitor c) Unix MonitorQ?/font> d) Trace/Kill session e) Oracle Parameter f) NLS_PARAMETER: g) Extents h) Tablespace i) Tablespace MapQ?/font> j) Server Statistics: k) Pinned CodeQ?/font> l) Control Files: 可以查看当前pȝ有哪几个控制文gQ以及控制文件内部记录的详细信息。(实际上就是V$CONTROLFILE, V$CONTROLFILE_RECORD_SECTIONQ?/font> m) Redo Log Manager: n) Repair chained rows: o) Identify Space Deficits 如果pȝ出现1659,1653错误Q就是一个不合格的DBA。但是要x预见q些错误Q还是有一定的隑ֺ的。有了Toad的这个小工具之后Q一Ҏ个表I间Q就知道q个表空间里面的剩余自由I间是否允许M表能够扩展到下一个extent。ƈ能够在发现问题之后,直接Ҏ问题?/font> p) Estimate Table/Index Size 1. 自己可以定义来表中需要存储的数据的数?/font> 2. 多种估计方式Q?/font> q) Analyze All Tables r) Rebuild Table s) Relocate Index t) Generate Schema ScriptsQ?/font> u) Compare SchemaQ?/font>
SUBQUERY SOLUTION ---------------------- SELECT st.stor_name AS 'Store', (SELECT SUM(bs.qty) FROM big_sales AS bs WHERE bs.stor_id = st.stor_id), 0) AS 'Books Sold' FROM stores AS st WHERE st.stor_id IN (SELECT DISTINCT stor_id FROM big_sales) | JOIN SOLUTION ---------------------- SELECT st.stor_name AS 'Store', SUM(bs.qty) AS 'Books Sold' FROM stores AS st JOIN big_sales AS bs ON bs.stor_id = st.stor_id WHERE st.stor_id IN (SELECT DISTINCT stor_id FROM big_sales) GROUP BY st.stor_name |
SUBQUERY SOLUTION ---------------------- SQL Server parse and compile time: CPU time = 28 ms elapsed time = 28 ms SQL Server Execution Times: CPU time = 145 ms elapsed time = 145 ms Table 'big_sales'. Scan count 14, logical reads 1884, physical reads 0, read-ahead reads 0. Table 'stores'. Scan count 12, logical reads 24, | JOIN SOLUTION ---------------------- SQL Server parse and compile time: CPU time = 50 ms elapsed time = 54 ms SQL Server Execution Times: CPU time = 109 ms elapsed time = 109 ms Table 'big_sales'. Scan count 14, logical reads 966, physical reads 0, read-ahead reads 0. Table 'stores'. Scan count 12, logical reads 24, |
不必更深探烦Q我们可以看到在CPU和ȝ实耗时间方面连接更快,仅需要子查询Ҏ逻辑ȝ一半。此外,q两U情况伴随着相同的结果集Q虽然排序的序不同Q这是因接查询(׃它的GROUP BY子句Q有一个隐含的ORDER BY:
Store Books Sold ------------------------------------------------- Barnum's 154125 Bookbeat 518080 Doc-U-Mat: Quality Laundry and Books 581130 Eric the Read Books 76931 Fricative Bookshop 259060 News & Brews 161090 (6 row(s) affected) Store Books Sold ------------------------------------------------- Eric the Read Books 76931 Barnum's 154125 News & Brews 161090 Doc-U-Mat: Quality Laundry and Books 581130 Fricative Bookshop 259060 Bookbeat 518080 (6 row(s) affected) |
|--Compute Scalar(DEFINE:([Expr1006]=isnull([Expr1004], 0))) |--Nested Loops(Left Outer Join, OUTER REFERENCES:([st].[stor_id])) |--Nested Loops(Inner Join, OUTER REFERENCES:([big_sales].[stor_id])) | |--Stream Aggregate(GROUP BY:([big_sales].[stor_id])) | | |--Clustered Index Scan(OBJECT:([pubs].[dbo].[big_sales]. [UPKCL_big_sales]), ORDERED FORWARD) | |--Clustered Index Seek(OBJECT:([pubs].[dbo].[stores].[UPK_storeid] AS [st]), SEEK:([st].[stor_id]=[big_sales].[stor_id]) ORDERED FORWARD) |--Stream Aggregate(DEFINE:([Expr1004]=SUM([bs].[qty]))) |--Clustered Index Seek(OBJECT:([pubs].[dbo].[big_sales]. [UPKCL_big_sales] AS [bs]), SEEK:([bs].[stor_id]=[st].[stor_id]) ORDERED FORWARD) |
|--Stream Aggregate(GROUP BY:([st].[stor_name]) DEFINE:([Expr1004]=SUM([partialagg1005]))) |--Sort(ORDER BY:([st].[stor_name] ASC)) |--Nested Loops(Left Semi Join, OUTER REFERENCES:([st].[stor_id])) |--Nested Loops(Inner Join, OUTER REFERENCES:([bs].[stor_id])) | |--Stream Aggregate(GROUP BY:([bs].[stor_id]) DEFINE:([partialagg1005]=SUM([bs].[qty]))) | | |--Clustered Index Scan(OBJECT:([pubs].[dbo].[big_sales]. [UPKCL_big_sales] AS [bs]), ORDERED FORWARD) | |--Clustered Index Seek(OBJECT:([pubs].[dbo].[stores]. [UPK_storeid] AS [st]), SEEK:([st].[stor_id]=[bs].[stor_id]) ORDERED FORWARD) |--Clustered Index Seek(OBJECT:([pubs].[dbo].[big_sales]. [UPKCL_big_sales]), SEEK:([big_sales].[stor_id]=[st].[stor_id]) ORDERED FORWARD) |
无论何时可能用UNION ALL 代替UNION。其中的差异是因为UNION有排除重复行q且对结果进行排序的副作用,而UNION ALL不会做这些工作。选择无重复行的结果需要徏立时工作表Q用它排序所有行q且在输Z前排序。(在一个select distinct 查询中显C查询计划将发现存在一个流聚合Q消耗百分之三十多的资源处理查询Q。当你确切知道你得需要时Q可以用UNION。但如果你估计在l果集中没有重复的行Q就使用UNION ALL吧。它只是从一个表或一个连接中选择Q然后从另一个表中选择Q附加在W一条结果集的底部。UNION ALL不需要工作表和排序(除非其它条g引v的)。在大部分情况下UNION ALL更具效率。一个有潜在危险的问题是使用UNION会在数据库中产生巨大的泛滥的临时工作表。如果你期望从UNION查询中获得大量的l果集时Q这可能发生?br />
CZ
下面的查询是选择pubs数据库中的表sales的所有商店的IDQ也选择表big_sales中的所有商店的IDQ这个表中我们加入了70Q?00多行数据。在q两个方案间不同之处仅仅是UNION 与UNION ALL的用比较。但在这个计划中加入ALL关键字生了三大不同。第一个方案中Q在q回l果集给客户端之前需要流聚合q且排序l果。第二个查询更有效率Q特别是对大表。在q个例子中两个查询返回同Ll果集,虽然序不同。在我们的测试中有两个时表。你的结果可能会E有差异?br />
UNION SOLUTION ----------------------- | UNION ALL SOLUTION ----------------------- |
SELECT stor_id FROM big_sales UNION SELECT stor_id FROM sales ---------------------------- | SELECT stor_id FROM big_sales UNION ALL SELECT stor_id FROM sales ---------------------------- |
|--Merge Join(Union) |--Stream Aggregate(GROUP BY: ([big_sales].[stor_id])) | |--Clustered Index Scan (OBJECT:([pubs].[dbo]. [big_sales]. [UPKCL_big_sales]), ORDERED FORWARD) |--Stream Aggregate(GROUP BY: ([sales].[stor_id])) |--Clustered Index Scan (OBJECT:([pubs].[dbo]. [sales].[UPKCL_sales]), ORDERED FORWARD) | |--Concatenation |--Index Scan (OBJECT:([pubs].[dbo]. [big_sales].[ndx_sales_ttlID])) |--Index Scan (OBJECT:([pubs].[dbo]. [sales].[titleidind])) |
UNION SOLUTION ----------------------- Table 'sales'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0. Table 'big_sales'. Scan count 1, logical reads 463, physical reads 0, read-ahead reads 0. | UNION ALL SOLUTION ----------------------- Table 'sales'. Scan count 1, logical reads 1, physical reads 0, read-ahead reads 0. Table 'big_sales'. Scan count 1, logical reads 224, physical reads 0, read-ahead reads 0. |
CZ
你应该帮助SQL ServerU除M在烦引数值列周围的表辑ּ。下面的查询是从表jobs通过唯一的聚集烦引的唯一键值选择出的一行。如果你在这个列上用表辑ּQ这个烦引就不v作用了。但一旦你条件’job_id-2=0?该成‘job_id=2’,优化器将在聚集烦引上执行seek操作?br />
QUERY WITH SUPPRESSED INDEX ----------------------- | OPTIMIZED QUERY USING INDEX ----------------------- |
SELECT * FROM jobs WHERE (job_id-2) = 0 | SELECT * FROM jobs WHERE job_id = 2 |
|--Clustered Index Scan(OBJECT: ([pubs].[dbo].[jobs]. [PK__jobs__117F9D94]), WHERE:(Convert([jobs].[job_id])- 2=0)) | |--Clustered Index Seek(OBJECT: ([pubs].[dbo].[jobs]. [PK__jobs__117F9D94]), SEEK:([jobs].[job_id]=Convert([@1])) ORDERED FORWARD) Note that a SEEK is much better than a SCAN, as in the previous query. |
下面表中列出了多U不同类型查询示例,其被止使用列烦引,同时l出改写的方法,以获得更优的性能?br />
QUERY WITH SUPPRESSED INDEX --------------------------------------- | OPTIMIZED QUERY USING INDEX -------------------------------------- |
DECLARE @job_id VARCHAR(5) SELECT @job_id = ?? SELECT * FROM jobs WHERE CONVERT( VARCHAR(5), job_id ) = @job_id ------------------------------- | DECLARE @job_id VARCHAR(5) SELECT @job_id = ?? SELECT * FROM jobs WHERE job_id = CONVERT( SMALLINT, @job_id ) ------------------------------- |
SELECT * FROM authors WHERE au_fname + ' ' + au_lname = 'Johnson White' ------------------------------- | SELECT * FROM authors WHERE au_fname = 'Johnson' AND au_lname = 'White' ------------------------------- |
SELECT * FROM authors WHERE SUBSTRING( au_lname, 1, 2 ) = 'Wh' ------------------------------- | SELECT * FROM authors WHERE au_lname LIKE 'Wh%' ------------------------------- |
CREATE INDEX employee_hire_date ON employee ( hire_date ) GO -- Get all employees hired -- in the 1st quarter of 1990: SELECT * FROM employee WHERE DATEPART( year, hire_date ) = 1990 AND DATEPART( quarter, hire_date ) = 1 ------------------------------- | CREATE INDEX employee_hire_date ON employee ( hire_date ) GO -- Get all employees hired -- in the 1st quarter of 1990: SELECT * FROM employee WHERE hire_date >= ?/1/1990? AND hire_date < ?/1/1990? ------------------------------- |
-- Suppose that hire_date may -- contain time other than 12AM -- Who was hired on 2/21/1990? SELECT * FROM employee WHERE CONVERT( CHAR(10), hire_date, 101 ) = ?/21/1990? | -- Suppose that hire_date may -- contain time other than 12AM -- Who was hired on 2/21/1990? SELECT * FROM employee WHERE hire_date >= ?/21/1990? AND hire_date < ?/22/1990?/p> |
为做个例子,一个文件含T-SQL批处理,其在big_sales表插入了9999行?br />
SELECT 语句中的TOP子句限制单个查询q回的行敎ͼ而SET ROWCOUNT限制所有后l查询媄响的行数。在很多~程d中这些命令提供了高效率?br /> SET ROWCOUNT在SELECTQINSERTQUPDATE OR DELETE语句中设|可以被影响的最大行数。这些设|在命o执行旉上生效ƈ且只影响当前的会话。ؓ了移除这个限制执行SET ROWCOUNT 0?br />一些实际的d用TOP or SET ROWCOUNT比用标准的SQL命o对编E是更有效率的。让我们在几个例子中证明Q?br />
TOP n
在几乎所有的数据库中最行的一个查询是h一个列表中的前NV在 pubs数据库案例中Q我们可以查N售最好CD的前五项。比较用TOPQSET ROWCOUNT和用ANSI SQL的三U方案?br />
U?ANSI SQL:
Select title,ytd_sales
From titles a
Where (select count(*)
From titles b
Where b.ytd_sales>a.ytd_sales
)<5
Order by ytd_sales DESC
q个UANSI SQLҎ执行一个效率可能很低的兌子查询,特别的在q个例子中,在ytd_sales上没有烦引支持。另外,q个U的标准SQL命o没有qo掉在ytd_sales的空?也没有区别多个CD间有兌的情c?
使用 SET ROWCOUNT:
SET ROWCOUNT 5
SELECT title, ytd_sales
FROM titles
ORDER BY ytd_sales DESC
SET ROWCOUNT 0
使用 TOP n:
SELECT TOP 5 title, ytd_sales
FROM titles
ORDER BY ytd_sales DESC
W二个方案用SET ROWCOUNT来停止SELECT查询Q而第三个Ҏ是当它找到前五行时用TOP n来停止。在q种情况下,在获得结果之前我们也要有一个ORDER BY子句强制Ҏ个表q行排序。两个查询的查询计划实际上是一L。然而,TOP优于SET ROWCOUNT的关键点是SET必须处理ORDER BY子句所需的工作表Q而TOP 不用?br />
在一个大表上Q我们可以在ytd_sales上创Z个烦引以避免排序。查询将使用该烦引找到前5行ƈ停止。与W一个方案相比较Q其扫描了整个表QƈҎ一行执行了一个关联子查询。在表上,性能的差异是很小的。但是在一个大表上Q第一个方案的处理旉可能是数个小Ӟ而后两个Ҏ是数U?br />
当确定查询需要时Q请考虑是否只需要其中几行,如果是,使用TOP子句节U大量时间?br />
Q北京铸锐数码科技有限公司 www.InnovateDigital.comQ?