SELECT dbo.Person_BasicInfo.*,
dbo.Graduater_GraduaterRegist.RegistNO AS RegistNO,
dbo.Graduater_GraduaterRegist.RegistTime AS BaoDaoTime,
dbo.Graduater_GraduaterRegist.RegistMan AS RegistMan,
dbo.Graduater_Business.ComeFrom AS ComeFrom,
dbo.Graduater_Business.Code AS Code,
dbo.Graduater_Business.Status AS Status,
dbo.Graduater_Business.ApproveResult AS ApproveResult,
dbo.Graduater_Business.NewCorp AS NewCorp,
dbo.Graduater_Business.CommendNumber AS CommendNumber,
dbo.Graduater_Business.EmployStatus AS EmployStatus,
dbo.Graduater_Business.NewCommendTime AS NewCommendTime,
dbo.Graduater_Business.GetSource AS GetSource,
dbo.Graduater_Business.EmployTime AS EmployTime,
dbo.Graduater_Business.Job AS Job,
dbo.Graduater_Business.FillMan AS FillMan,
dbo.Graduater_Business.FillTime AS FillTime,
dbo.Graduater_Business.IsCommendOK AS IsCommendOK,
dbo.Graduater_Business.ApproveUser AS ApproveUser,
dbo.Graduater_Business.ApproveTime AS ApproveTime,
dbo.Graduater_Business.RegistTime AS RegistTime,
dbo.Graduater_Business.EmployCorp AS EmployCorp,
dbo.Graduater_Business.JobRemark AS JobRemark,
CASE WHEN dbo.Graduater_Business.ComeFrom = 'WS' THEN '网上登记'
WHEN dbo.Graduater_Business.ComeFrom = 'HP' THEN '华普大厦'
WHEN dbo.Graduater_Business.ComeFrom = 'JD' THEN '精典大厦'
WHEN dbo.Graduater_Business.ComeFrom = 'MC' THEN '赛马场'
WHEN ComeFrom = 'ZX' THEN '高指中心' END AS ComeFromName,
dbo.Person_Contact.Address AS Address,
dbo.Person_Contact.Zip AS Zip,
dbo.Person_Contact.Telephone AS Telephone,
dbo.Person_Contact.Mobile AS Mobile,
dbo.Person_Contact.Email AS Email,
dbo.Person_Contact.IM AS IM,
dbo.Person_Skill.ForeignLanguage AS ForeignLanguage,
dbo.Person_Skill.ForeignLanguageLevel AS ForeignLanguageLevel,
dbo.Person_Skill.CantoneseLevel AS CantoneseLevel,
dbo.Person_Skill.MandarinLevel AS MandarinLevel,
dbo.Person_Skill.Language AS Language,
dbo.Person_Skill.TechnicalTitle AS TechnicalTitle,
dbo.Person_Skill.ComputerLevel AS ComputerLevel,
dbo.Person_EmployPurpose.JobType AS JobType,
dbo.Person_EmployPurpose.Vocation AS Vocation,
dbo.Person_EmployPurpose.JobPlace AS JobPlace,
dbo.Person_EmployPurpose.Salary AS Salary,
dbo.Person_EmployPurpose.OnJobDate AS OnJobDate,
dbo.Person_EmployPurpose.CorpType AS CorpType,
dbo.Person_EmployPurpose.Job AS RequireJob,
YEAR(GETDATE()) - YEAR(dbo.Person_BasicInfo.Birthday) AS Age,
dbo.Graduater_Business.EmployType AS EmployType,
dbo.Graduater_Business.EmployTypeCode AS EmployTypeCode,
dbo.Graduater_Business.EmployCorpType AS EmployCorpType,
CASE WHEN dbo.Graduater_Business.PrintStatus = '已打印' THEN '已打印'
ELSE '未打印' END AS PrintStatus,
dbo.Graduater_Business.PrintTime AS PrintTime,
CASE WHEN dbo.Graduater_Business.EmployStatus = '是' THEN '已就业'
ELSE '未就业' END AS EmployStatusView
FROM dbo.Person_BasicInfo
INNER JOIN dbo.Graduater_Business
ON dbo.Person_BasicInfo.PersonID = dbo.Graduater_Business.PersonID
LEFT OUTER JOIN dbo.Graduater_GraduaterRegist
ON dbo.Graduater_Business.GradBusinessID = dbo.Graduater_GraduaterRegist.GraduaterGUID
INNER JOIN dbo.Person_Contact
ON dbo.Person_BasicInfo.PersonID = dbo.Person_Contact.PersonID
INNER JOIN dbo.Person_Skill
ON dbo.Person_BasicInfo.PersonID = dbo.Person_Skill.PersonID
INNER JOIN dbo.Person_EmployPurpose
ON dbo.Person_BasicInfo.PersonID = dbo.Person_EmployPurpose.PersonID
OPTION (FORCE ORDER)
(
通过上面的步骤,我们已经可以实现自动优化SQL语句,但更重要的是,我们还可以学习如何书写这样高性能的SQL语句。点击界面左方的“Compare Scenarios”按钮,我们可以比较优化方案和原始SQL中的任意2条SQL语句,SQL Tuning会将它们之间的不同之处以不同颜色表示出来,
还可以在下方的“执行计划”中,通过比较两条SQL语句的执行计划的不同,来了解其中的差异(图8)。
EXPLAIN PLAN SET STATEMENT_ID = 'test1' FOR
SET STATEMENT_ID = 'RUN1'
INTO plan_table
FOR
SELECT 'T'||plansnet.terr_code, 'P'||detplan.pac1
|| detplan.pac2 || detplan.pac3, 'P1', sum(plansnet.ytd_d_ly_tm),
sum(plansnet.ytd_d_ty_tm),
sum(plansnet.jan_d_ly),
sum(plansnet.jan_d_ty),
FROM plansnet, detplan
WHERE
plansnet.mgc = detplan.mktgpm
AND
detplan.pac1 in ('N33','192','195','201','BAI',
'P51','Q27','180','181','183','184','186','188',
'198','204','207','209','211')
GROUP BY 'T'||plansnet.terr_code, 'P'||detplan.pac1 || detplan.pac2 || detplan.pac3;
operation
表明当前语句完成的操作,通常包括table access, table merge, sort, or index operation
options
补充说明operation,像full table, range table, join
object_name
查询组件的名字
Process ID
查询组件的ID号
Parent_ID
查询组建的父ID,注意,有些查询会有一个相同的父ID
现在plan_table已经被填充,可以使用下面的查询来查看当前SQL语句的执行计划。
plan.sql - displays contents of the explain plan table
SET PAGES 9999;
SELECT lpad(' ',2*(level-1))||operation operation,
options,
object_name,
position
FROM plan_table
START WITH id=0
AND
statement_id = 'RUN1'
CONNECT BY prior id = parent_id
AND
statement_id = 'RUN1';
d.重写NOT EXISTS和查询作为外部连接NOT EXISTS 子查询
在一些案例中的NOT 查询(where 中一个列被定义为NULL值),能够将其改写这个非相关子查询到IS NULL 的外部链接。如下例:
select book_key from book
where
book_key NOT IN (select book_key from sales);
下面我们在where子句中使用了外部连接来替代原来的not exits,得到一个更高效的执行计划。
select b.book_key from book b, sales s
where
b.book_key = s.book_key(+)
and
s.book_key IS NULL;
e.索引NULL值列
如果你的SQL语句频繁使用到NULL值,应当考虑基于NULL值创建索引。为使该查询最优化,可以创建一个使用基于NULL值索引函数。
(译者按,如 create index i_tb_col on tab(nvl(col,null)); create index i_tb_col on tab(col,0);)
f.避免基于索引的运算
不要基于索引列做任何运算,除非你创建了一个相应的索引函数。或者重设设计列以使得where子句列上的谓词不需要转换。
-->下面都是低效的SQL写法
where salary*5 > :myvalue
where substr(ssn,7,4) = "1234"
where to_char(mydate,mon) = "january"
g.避免使用NOT IN 和HAVING
在合适的时候使用not exists子查询更高效。
h.避免使用LIKE谓词
在合适地时候,如果能够使用 = 运算应尽可能避免LIKE操作。
i.避免数据类型转换
如果一个where 子句列是数字型,则不要使用引号。而对一个字符索引列,总是使用引号。下面是数据类型混用的情形。
where cust_nbr = "123"
where substr(ssn,7,4) = 1234