一个简单的sql审核案例

简介: 今天开发的同学发来一封邮件,希望我帮忙对一个sql语句做一个评估。他们也着急要用,但是为了稳妥起见,还是希望我来审核一下,这是一个好的习惯。 打开邮件,看到的语句是下面这样的形式。
今天开发的同学发来一封邮件,希望我帮忙对一个sql语句做一个评估。他们也着急要用,但是为了稳妥起见,还是希望我来审核一下,这是一个好的习惯。
打开邮件,看到的语句是下面这样的形式。
select a.cout1+b.cout2 from (select count(*) as cout1 from TEST_ONLINE where CN='' and to_char(LOGIN_TIME,'yyyymmdd') = to_char(sysdate,'yyyymmdd') and rownum = 1) a,(select count(*) as cout2 from TEST_USER_CENTER where CN='' and to_char(LAST_LOGOUT,'yyyymmdd') = to_char(sysdate,'yyyymmdd') and rownum = 1) b;
看到这个语句,确实需要审核。
首先从sql语句结构上来说,实在不够好。
如果两个子查询的结果集条数大于1,很可能走笛卡尔积,貌似开发的同学也注意到了这一点,在两个子查询的末尾都加了rownum=1的字样,这样就肯定能够保证语句能够始终有1条以内的记录显示。所以这个语句看起来可以调整的空间不大。
但是我们做sql审核,也离不开表的属性信息。这两个表是OLTP的数据表,里面会有大量的实时数据变化,看看两个子查询中的过滤条件,是根据日期来作为单位统计的,而一个核心字段就是CN了。看到这种情况,如果每日存在大量的数据,使用to_char(LAST_LOGOUT,'yyyymmdd')这种方式肯定是有弊端,但是看需求是想精确到日为单位的数据,那么在这种情况下的关键就是CN了。
带着疑问继续查看,发现CN在两个表中都是主键,那么这种情况就好办多了。对于日期带来的困扰,其实影响不大,而且根据数据的分布,一个CN对应的数据是唯一性的,那么使用rownum=1就有些多余了,然后再来看日期的过滤,有了CN的唯一性约束过滤,数据要么有匹配的是1条,要么就是没有匹配的0条。
结果也是显而易见,明白了这一点,这个时候看起来思路就清晰多了,这个查询的结果应该是在0~2之间。
对于这个语句有了更深入一步的认识,我们就来简单的改造一下。
这样的形式:
select a.cout1+b.cout2 from (select count(*) as cout1 from TEST_ONLINE where CN='xxx' and to_char(LOGIN_TIME,'yyyymmdd') = to_char(sysdate,'yyyymmdd')) a,(select count(*) as cout2 from TEST_USER_CENTER where CN='xxx' and to_char(LAST_LOGOUT,'yyyymmdd') = to_char(sysdate,'yyyymmdd') ) b;
或者:
select  (select count(*) as cout1 from TEST_ONLINE where CN='xxx' and to_char(LOGIN_TIME,'yyyymmdd') = to_char(sysdate,'yyyymmdd') ) +(select count(*) as cout2 from TEST_USER_CENTER where CN='xxx' and to_char(LAST_LOGOUT,'yyyymmdd') = to_char(sysdate,'yyyymmdd') )  from dual;
或者使用with
with
a as (select count(*) as cout1 from TEST_ONLINE where CN='xxx' and to_char(LOGIN_TIME,'yyyymmdd') = to_char(sysdate,'yyyymmdd') and ),
b as (select count(*) as cout2 from TEST_USER_CENTER where CN='xxx' and to_char(LAST_LOGOUT,'yyyymmdd') = to_char(sysdate,'yyyymmdd') )
select a.count1+b.count2 from a,b;
在目前满足条件的情况下,性能差别应该不大。如果CN为非唯一性约束,这个问题还是需要好好斟酌一下了,如果在LOGIN_TIME,LOGOUT_TIME上有索引还是需要避免使用日期的二次格式化,而且在这个基础上,我应该在末尾使用group by而不是rownum=1了。
这样语句可能就变成了下面的形式。
select a.cout1+b.cout2 from (select count(*) as cout1 from TEST_ONLINE where CN='xxx' and LOGIN_TIME between trunc(sysdate) and to_date(sysdate,'yyyy-mm-dd hh24:mi:ss')  group by LOGIN_TIME) a,(select count(*) as cout2 from TEST_USER_CENTER where CN='xxx' and LOGOUT_TIME between trunc(sysdate) and to_date(sysdate,'yyyy-mm-dd hh24:mi:ss')
group by LOGOUT_TIME) b;
还有其它更多的改进方法,暂且讨论到这里。


目录
相关文章
|
7月前
|
SQL 关系型数据库 MySQL
Linux系统部署Yearning SQL审核平台结合内网穿透实现公网访问
Linux系统部署Yearning SQL审核平台结合内网穿透实现公网访问
|
3月前
|
SQL 数据库
数据库数据恢复—SQL Server数据库报错“错误823”的数据恢复案例
SQL Server附加数据库出现错误823,附加数据库失败。数据库没有备份,无法通过备份恢复数据库。 SQL Server数据库出现823错误的可能原因有:数据库物理页面损坏、数据库物理页面校验值损坏导致无法识别该页面、断电或者文件系统问题导致页面丢失。
114 12
数据库数据恢复—SQL Server数据库报错“错误823”的数据恢复案例
|
20天前
|
SQL 监控 安全
SQL Servers审核提高数据库安全性
SQL Server审核是一种追踪和审查SQL Server上所有活动的机制,旨在检测潜在威胁和漏洞,监控服务器设置的更改。审核日志记录安全问题和数据泄露的详细信息,帮助管理员追踪数据库中的特定活动,确保数据安全和合规性。SQL Server审核分为服务器级和数据库级,涵盖登录、配置变更和数据操作等事件。审核工具如EventLog Analyzer提供实时监控和即时告警,帮助快速响应安全事件。
|
27天前
|
SQL 数据库
gbase 8a 数据库 SQL优化案例-关联顺序优化
gbase 8a 数据库 SQL优化案例-关联顺序优化
|
1月前
|
SQL 数据库 UED
SQL性能提升秘籍:5步优化法与10个实战案例
在数据库管理和应用开发中,SQL查询的性能优化至关重要。高效的SQL查询不仅可以提高应用的响应速度,还能降低服务器负载,提升用户体验。本文将分享SQL优化的五大步骤和十个实战案例,帮助构建高效、稳定的数据库应用。
63 3
|
1月前
|
SQL 缓存 监控
SQL性能提升指南:五大优化策略与十个实战案例
在数据库性能优化的世界里,SQL优化是提升查询效率的关键。一个高效的SQL查询可以显著减少数据库的负载,提高应用响应速度,甚至影响整个系统的稳定性和扩展性。本文将介绍SQL优化的五大步骤,并结合十个实战案例,为你提供一份详尽的性能提升指南。
51 0
|
6月前
|
SQL 监控 关系型数据库
实际应用中监控和诊断SQL语句执行情况的具体案例
实际应用中监控和诊断SQL语句执行情况的具体案例
101 3
|
2月前
|
SQL 大数据 API
大数据-132 - Flink SQL 基本介绍 与 HelloWorld案例
大数据-132 - Flink SQL 基本介绍 与 HelloWorld案例
60 0
|
4月前
|
SQL 存储 关系型数据库
5大步骤+10个案例,堪称SQL优化万能公式
5大步骤+10个案例,堪称SQL优化万能公式
|
5月前
|
SQL 存储 安全
数据库数据恢复—SQL Server数据库出现逻辑错误的数据恢复案例
SQL Server数据库数据恢复环境: 某品牌服务器存储中有两组raid5磁盘阵列。操作系统层面跑着SQL Server数据库,SQL Server数据库存放在D盘分区中。 SQL Server数据库故障: 存放SQL Server数据库的D盘分区容量不足,管理员在E盘中生成了一个.ndf的文件并且将数据库路径指向E盘继续使用。数据库继续运行一段时间后出现故障并报错,连接失效,SqlServer数据库无法附加查询。管理员多次尝试恢复数据库数据但是没有成功。