低效能的”where1=1”
网上有不少人提出过类似的问题:“看到有人写了where 1=1这种sql,究竟是什么意思?”。事实上使用这种使用方法的开发者一般都是在使用动态数组的sql。
让我们想象例如以下的场景:用户要求提供一个灵活的查询界面来依据各种复杂的条件查询员工信息,界面例如以下图:
界面中列出了四个查询条件,包含按工号查询、按姓名查询、按年两查询以及按工资查询。每一个查询条件前都有个复选框,假设复选框被选中,则表示将其作为一个过滤条件。
比方上图就表示“检索工号介于001和008之间、姓名中含有J而且工资介于3000到6000的员工信息”。
假设不选中姓名前的复选框,比方下图表示“检索工号介于001和008之间
而且工资介于3000到6000的员工信息”:
假设全部的复选框都不选中,则表示“检索全部员工信息”,比方下图:
这里的数据检索与前面的检索不一样,由于前边样例中的数据检索的过滤条件都是确定的。而这里的过滤条件则随着用户设置的不同而有变化,这时就要依据用户的设置来动态
组装sql了。当不选中年龄前的复选框的时候要使用以下的SQL语句:
SELECT * FROM T_Employee
WHERE FNumber BETWEEN '001' AND '008'
AND FName LIKE '%J%'
AND FSalary BETWEEN 3000 AND 6000
而假设不选中姓名和年龄前的复选框的时候就要使用以下的SQL语句:
SELECT * FROM T_Employee
WHERE FNumber BETWEEN '001' AND '008'
AND FSalary BETWEEN 3000 AND 6000
而假设将全部的复选框都不选中的时候就要使用以下的SQL语句:
SELECT * FROM T_Employee
要实现这样的动态的SQL语句拼装,我们能够在宿主语言中建立一个字符串。然后逐个推断各个复选框是否选中来向这个字符串中加入SQL语句片段。这里有一个问题就是当有复
选框被选中的时候SQL语句是含有WHERE子句的。而当全部的复选框都没有被选中的时候就没有WHERE子句了,因此在加入每个过滤条件推断的时候都要推断是否已经存
在WHERE语句了。假设没有WHERE语句则加入WHERE语句。
在推断每个复选框的时候都要去推断。这使得用起来很麻烦,“聪明的程序猿是会偷懒的程序猿”。因此开发
人员想到了一个捷径:为SQL语句指定一个永远为真的条件语句(比方“1=1”),这样就不用考虑WHERE语句是否存在的问题了。伪代码例如以下:
String sql = " SELECT * FROM T_Employee WHERE 1=1";
if(工号复选框选中)
{
sql.appendLine("AND FNumber BETWEEN '"+工号文本框1内容+"' AND '"+工号
文本框2内容+"'");
}
if(姓名复选框选中)
{
sql.appendLine("AND FName LIKE '%"+姓名文本框内容+"%'");
}
if(年龄复选框选中)
{
sql.appendLine("AND FAge BETWEEN "+年龄文本框1内容+" AND "+年龄文本框2
内容);
}
executeSQL(sql);
这样假设不选中姓名和年龄前的复选框的时候就会运行以下的SQL语句:
SELECT * FROM T_Employee WHERE 1=1
AND FNumber BETWEEN 'DEV001' AND 'DEV008'
AND FSalary BETWEEN 3000 AND 6000
而假设将全部的复选框都不选中的时候就会运行以下的SQL语句:
SELECT * FROM T_Employee WHERE 1=1
这看似很优美的攻克了问题。殊不知这样很可能会造成很大的性能损失,由于使用加入了“1=1”的过滤条件以后数据库系统就无法使用索引等查询优化策略。数据库系统将
会被迫对每行数据进行扫描(也就是全表扫描)以比較此行是否满足过滤条件。当表中数据量比較大的时候查询速度会很慢。
因此假设数据检索对性能有比較高的要求就不要
使用这样的“简便”的方式。以下给出一种參考实现。伪代码例如以下:
private void doQuery()
{
Bool hasWhere = false;
StringBuilder sql = new StringBuilder(" SELECT * FROM T_Employee");
if(工号复选框选中)
{
hasWhere = appendWhereIfNeed(sql, hasWhere);
sql.appendLine("FNumber BETWEEN '"+工号文本框1内容+"' AND '"+工号
文本框2内容+"'");
}
if(姓名复选框选中)
{
hasWhere = appendWhereIfNeed(sql, hasWhere);
sql.appendLine("FName LIKE '%"+姓名文本框内容+"%'");
}
if(年龄复选框选中)
{
hasWhere = appendWhereIfNeed(sql, hasWhere);
sql.appendLine("FAge BETWEEN "+年龄文本框1内容+" AND "+年龄文本框2
内容);
}
executeSQL(sql);
}
private Bool appendWhereIfNeed(StringBuilder sql,Bool hasWhere)
{
if(hasWhere==false)
{
sql. appendLine("WHERE");
}
else
{
sql. appendLine("AND");
}
}
低效能的”where1=1”的更多相关文章
- PLSQL_低效SQL的识别和查询汇总(案例)
2014-12-18 Created By BaoXinjian
- 如何找出MySQL数据库中的低效SQL语句
面对业务的迅猛发展,DBA的一项重要工作就是及时发现数据库中的低效SQL语句,有的可以立刻着手解决(比如缺少合适的索引),有的需要尽快反馈给开发人员进行修改. MySQL数据库有几个配置选项可以帮助我 ...
- 通过dbms_xplan.display_cursor识别低效的执行计划
dbms_xplan.display_cursor定义: function display_cursor(sql_id varchar2 default null, ...
- 一个令人困惑的低效SQL
整理之前的优化案例,觉得下面这个应该是开发很难发现也会很困惑的一个低效SQL. 看下面这个SQL.你看到这个SQL会不会感觉很正常.其实我刚看到也觉得正常得不得了.但是测试后它确实效率很低.selec ...
- 低效的SQL引发的cache buffers chains latch
1.低效的SQL 低效的SQL语句时发生cache buffers chains 锁存器争用的最重要原因.多个进程同时扫描大范围的索引或表时,可能广泛 地发生cache buffers chains ...
- SQL调优学习之——sqlserver分页从低效到高效
背景 首先感谢网友@aixuexi 在评论中的提醒,原博文介绍的几种都不是最高效,现已修改加入另一种更高效的方法. 以前都是使用mysql和oracle,对sqlserver的使用不多.最近因项目原因 ...
- 秒杀场景下MySQL的低效(转)
秒杀场景下MySQL的低效 2016-01-14 17:12 178人阅读 评论(0) 收藏 举报 最近业务试水电商,接了一个秒杀的活.之前经常看到淘宝的同行们讨论秒杀,讨论电商,这次终于轮到我们自己 ...
- 【转载】秒杀场景下MySQL的低效原因和改进以及Redis的处理
分享的PPT在如下网址: http://www.doc88.com/p-4199037770087.html 秒杀场景下mysql的低效原因和改进 另外有一个篇文章是针对以上内容的总结: http:/ ...
- CPU和GPU双低效,摩尔定律之后一万倍 ——写于TPU版AlphaGo重出江湖之际
本文来自计算机体系结构专家王逵.他认为,“摩尔定律结束之后,性能提升一万倍”不会是科幻,而是发生在我们眼前的事实. 2008年,<三体2:黑暗森林>里写到: 真的很难,你冬眠后不久 ...
- 使用std::function改善模板的低效性
泛型编程中,模板会根据传入类型的不同,生成多种实例,相对低效. 模板编程: #include <iostream> using namespace std; //未使用函数包装器 temp ...
随机推荐
- SpringMVC 理论与有用技术(二)文件上传
文件上传相信大家都做过,差点儿全部的项目都有上传文件的功能,尤其是BS架构的项目中经常被列为常规功能来开发.不管是在开发.NET 项目还是java项目我们会用到非常多的框架,这个功能也被集成到了框架之 ...
- Android接口和框架学习
Android接口和框架学习 缩写: HAL:HardwareAbstraction Layer.硬件抽象层 CTS:CompatibilityTest Suite,兼容性測试套件 Android让你 ...
- Spring In Action读书笔记
第一章 1.Spring採用4种策略减少Java开发复杂度 基于POJO的轻量级和最小侵入性编程 依赖注入和面向接口实现松耦合 基于切面和惯例进行声明式编程 通过切面和模板降低样板式代码 PS:POJ ...
- Java专业技能面试问题(不定时更新)
刚看到园友五月的仓颉<面试感悟----一名3年工作经验的程序员应该具备的技能>感觉很不错,不论是为面试跳槽准备,还是打算深化精进自己的技术都可以参考一下.面向工资编程多少也有点道理,虽然技 ...
- ubuntu中不能远程连接解决
今天装好ubuntu19.04之后不能远程连接,网上找了很久终于自己解决了.ap 步骤如下:希望对各位有用,哪里不对请指出 第一步我们需要加载openssh-server 等待加载完毕后, ...
- 在centOS 6.5下手动安装nginx1.9.x版本
第一步:首先安装Nginx的依赖环境 1.安装pcre-devel yum -y install pcre-devel #支持正则的pcre模块 比如安装 不然手动安装会报错 2.安 ...
- 转:如何在Ubuntu 14.04中安装最新版Eclipse
想必很多开发人员都知道,Ubuntu 软件源中提供的并不是最新版本的 Eclipse,本教程就教大家如何在 Ubuntu 14.04 中快速安装 Eclipse 官方发布的最新版本. 到目前为止,Ec ...
- SQL Server 获取两个日期间的日期
declare @start datetime declare @end datetime set @start = '2018-01-25' set @end = '2018-02-03' sele ...
- BZOJ4819: [Sdoi2017]新生舞会(01分数规划)
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1029 Solved: 528[Submit][Status][Discuss] Descripti ...
- datatable.rows.indexof(dr)返回的是啥?
返回的是Int类型的 行索引值,从0开始.也就是说,第一行是0.最后一行就是rows.count - 1.不会返回-1."这是第" + OldDt.Rows.IndexOf(ite ...