低效能的”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 ...
随机推荐
- httpurlconnection get String
public static String getJSON(String url, int timeout) { HttpURLConnection c = null; try { long reque ...
- ios OpenCv的配置和人脸识别技术
作为一个好奇心非常重的人,面对未知的世界都想去一探到底. 于是做了个人脸识别的demo. 眼下国内的关于opencv技术文章非常少.都是互相抄袭.关键是抄个一小部分还不全.时间又是非常久之前的了,和如 ...
- 我的Android进阶之旅------>android Button上面的英文字符串自己主动大写的问题解决
今天碰到一个关于Button的问题:android Button上面的英文字符串会自己主动变成大写,执行的Android 5.1版本号,例如以下图所看到的: 图1:Button 图2:TextView ...
- 创建多线程的HttpClient
在实际的应用中,我们的联网应用程序里应该有一个HttpClient,并将其用于所有的HTTP通信.这就可能在同一个Http Client同时发出多个请求,也就产生了多线程的问题.幸运的是,在HttpC ...
- hdoj--1276--士兵队列训练问题(数组模拟)
士兵队列训练问题 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- Reusability1
Reusability 1. 复用的层面 1.1 代码级别复用 顾名思义,代码复用就是把代码都搬过来,这是最主要的复用 1.1.1 白盒复用 白盒的意思就是里面的东西我们都知道是什么,具体实现的方式也 ...
- C# 实现透明可移动窗体
1.设置窗体属性 this.BackColor this.TransparencyKey = this.BackColor; 2.窗体加载图片 this.BackgroundImage = globa ...
- Core篇——初探Core配置管理
文章目录 1.命令行配置 2.Json文件配置 3.配置文件文本至C#对象实例的映射 4.配置文件热更新 5.总结 命令行的配置 我们首先来创建一个.net core 的控制台项目,然后引入.net ...
- python中set集合的使用
集合(set):把不同的元素组成一起形成集合,是python基本的数据类型. python 的集合类型和 其他语言类似, 是一个无序不重复元素集 基本功能包括关系测试和消除重复元素.集合对象还支持un ...
- PHP 导出excel 数据量大时
public function ceshiexcel1(){ set_time_limit(0); $filename = '病毒日志'; header('Content-Type: applicat ...