`

低效的where 1=1

 
阅读更多
 
  也许很多人在开发多条件查询或模糊查询的时候,为保证不管选择哪种过滤条件总保证查询条件为true,于是在where子句后选择1=1或者0=0技巧来满足模糊查询。当然这的确对开发人员来说是一个不错的技巧。于是我在Mysql中通过上千万条的数据测试发现很耗性能。即便是建了常用字段的索引(排序)也没有作用,足以确定1=1很低效,大数据量很耗性能。

  select * from t_user where 1=1

   因为添加了"1=1"的过滤条件以后数据库系统无法使用索引等优化查询策略,数据库系统将会被迫对每行数据进行扫描(也就是全表扫描)来比较此行是否满足顾虑条件,当表中数据量比较大的时候查询速度会非常慢。


--------------------
maoone2003的回答甚是不错(红色部分) 作为开题人 我采纳...

select * from table where 1=1因为table中根本就没有名称为1的字段,所以该SQL等效于select * from table,这个SQL语句很明显是全表扫描,需要大量的IO操作,数据量越大越慢,建议查询时增加必输项,即where 1=1后面追加一些常用的必选条件,并且将这些必选条件建立适当的索引,效率会大大提高
PS:这不是SQL写法的问题,也不是数据库的问题,是自己程序逻辑的问题


分享到:
评论
61 楼 xiaoZ5919 2010-07-13  
pi1ot 写道
我怎么从来没遇到过需要这么用的时候,举个例子

组合查询条件时一般这么干,防止where后面没有任何的谓词。
60 楼 xiaoZ5919 2010-07-13  
seanzeng 写道
你把执行计划打开看看有没有区别好不?mysql不会这么弱智的吧。

我记得在一般MySQL的书上看到。where 1=1 确实采用的是全表扫描。
lz,你执行explain试过了吗?
59 楼 windywany 2010-07-13  
老天呀,培训机构害死人呀,不教好的,只教坏的. 加1=1 就是为了在没有指定查询条件时查询语句不出错.你们真的是懒到家了.这与数据库真的一点关系都没有.数据库凭什么要为你们的错误而承担责任?请为自己的代码负责.我说下php中的一个解决方案(不知道为什么我不能贴代码).

$sql = "SELECT * FROM table1 WHERE ";
$cons = array();
if($xxx){
    $cons[] = "xxx = $xxx";
}
if($yyy){
    $cons[] = "xxx LIKE '$yyy%'";
}

...................

$cons = join(" AND ",$cons);
$sql  = rtrim($sql.$cons,'WHERE ');

如果1=1真的影响性能,那就让1=1从你的代码中消失吧.如果你的语言里没有join,rtrim这样功能的函数或者说连接数组都没有,那可能就是数据库的错.
58 楼 weiqiang.yang 2010-07-13  
stefanoli_0705 写道
pi1ot 写道
我怎么从来没遇到过需要这么用的时候,举个例子


我们公司在应用ibatis查询的时候,很多这么写,确实比较省事


ibatis也会用到这种写法??
我觉得ibatis最方便的地方就是动态组合各种查询条件

select * from Table
<dynamic prepend="where">
    <isNotNull .... prepend="and">...</isNotNull>
    .....
</dynamic>


就算isNotNull条件成立,也不会出现where and语句,ibatis已经处理好了
57 楼 shijian0306 2010-07-13  
ywlqi 写道
Das_flamen 写道
superyang 写道
抛出异常的爱 写道
 
StringBuffer buffer = new StringBuffer("select * from T where 1=1 ");
for(Map.Enty e : map){
    buffer .appand ("and "+ e.getKey()+" = '"+e.getValue()+"'");
}




		String hql = "select e.id,e.name,e.provice,e.city,e.total,date_format(e.addtime,'%Y-%m-%d'),a.name,date_format(e.sendtime,'%Y-%m-%d') from email e,admin a where e.add_admin_id=a.id";

		if (!this.isNull(email_type)) {

			hql += " and e.name like '%" + email_type + "%'";
		}
		if (!this.isNull(provice)) {

			hql += " and e.provice like '%" + provice + "%'";
		}
		if (!this.isNull(city)) {

			hql += " and e.city like '%" + city + "%'";
		}
		if (!this.isNull(name)) {

			hql += " and e.name like '%" + name + "%'";
		}
		if (!this.isNull(add_admin_id)) {

			hql += " and e.adminByAddAdminId.id='" + add_admin_id + "'";
		}
		if (!this.isNull(order_type)) {

			String arr[] = order_type.split("_");
			hql += " order by e." + arr[0] + " " + arr[1];
			hql += ",e.addtime desc";
		} else {
			hql += " e.addtime desc";
		}
	
		



这样写可不可以??
为什么很多人用StringBuffer的..???

你可以去试下,StringBuffer的效率不是String能比的,拼接的时候String多了严重影响性能。当然,如果就几条那也没什么,不过强烈推荐不要用String,不是个好习惯。


我记得有帖子说过jdk1.5以后对字符串相加做了优化,效率和StringBuffer一样了啊,我没做过实验,谁做过实验的来说两句


一个是线程安全的,一个不是现成的,你说那个快。。。
56 楼 shijian0306 2010-07-13  
superyang 写道
maozj 写道
superyang 写道
好像是很低效,一个邮件收集系统才10万多条数据就已经变得很慢了,也查不出是什原因..(mysql5.0)


以前是这样的hql:
select e.id,e.name,date_format(e.addtime,'%Y-%m-%d'),e.admin.name,date_format(e.sendtime,'%Y-%m-%d') from email e where 1=1;

现在改为这样native-sql:
select e.id,e.name,date_format(e.addtime,'%Y-%m-%d'),a.name,date_format(e.sendtime,'%Y-%m-%d') from email e,admin a where e.add_admin_id=a.id
也是很慢.


---

select count(e.id) from email e where 1=1







查询到数据量为5万多,点分页就快一点.
查询全部数据量,点分页就相当慢.

很欣慰你的细腻



能分析一下是什么问题?
能解决吗?

赏分:100分...




加索引了没有,数据量不是很大啊
55 楼 mathfox 2010-07-13  
maozj 写道
即便用到索引 也不会用到其优化性


都全表扫描了,还什么索引啊。
54 楼 java_web 2010-07-13  
stefanoli_0705 写道
pi1ot 写道
我怎么从来没遇到过需要这么用的时候,举个例子


我们公司在应用ibatis查询的时候,很多这么写,确实比较省事


用ibatis完全可以用其他的方法实现。就像官方文档写的:

MyBatis 有个简单的方案就能解决这里面90%的问题。如果where 没有出现的时候,你可以自定一个。
稍稍修改一下,就能完全解决:
<select id=”findActiveBlogLike”
parameterType=”Blog” resultType=”Blog”>
SELECT * FROM BLOG
<where>
<if test=”state != null”>
state = #{state}
</if>
<if test=”title != null”>
AND title like #{title}
</if>
<if test=”author != null and author.name != null”>
AND title like #{author.name}
</if>
</where>
</select>

这个“where”元素会知道如果它包含的标签中有返回值的话,它就插入一个‘where’。此外,如果标签
返回的内容是以AND 或OR 开头的,则它会剔除掉。
如果where 元素并没有完全按你想要的那样,那你也可以使用trim 元素自定义它。下面的trim 也相同于
where:
<trim prefix="WHERE" prefixOverrides="AND |OR ">
…
</trim>
53 楼 抛出异常的爱 2010-07-13  
sundoctor 写道
where 1=1看起来很笨,很别扭,见过很多人这样写,本人很是反感

本质上是为了节约二个if而已.
StringBuffer buffer = new StringBuffer("select * from T ");

if (!haveNoPara(map)){
  boolean isFirst = true;
  for(Map.Enty e : map){
      if(isFirst){
          buffer.appand(" where ");
          isFirst = false;
      }else{     
          buffer .appand(" and ");
      }
     buffer .appand ( e.getKey()+" = '"+e.getValue()+"'");
  }
}

 
StringBuffer buffer = new StringBuffer("select * from T where 1=1 ");
for(Map.Enty e : map){
    buffer .appand ("and "+ e.getKey()+" = '"+e.getValue()+"'");
}
52 楼 sundoctor 2010-07-13  
where 1=1看起来很笨,很别扭,见过很多人这样写,本人很是反感
51 楼 抛出异常的爱 2010-07-13  
qchong 写道
ywlqi 写道
Das_flamen 写道
superyang 写道
抛出异常的爱 写道
 
StringBuffer buffer = new StringBuffer("select * from T where 1=1 ");
for(Map.Enty e : map){
    buffer .appand ("and "+ e.getKey()+" = '"+e.getValue()+"'");
}




		String hql = "select e.id,e.name,e.provice,e.city,e.total,date_format(e.addtime,'%Y-%m-%d'),a.name,date_format(e.sendtime,'%Y-%m-%d') from email e,admin a where e.add_admin_id=a.id";

		if (!this.isNull(email_type)) {

			hql += " and e.name like '%" + email_type + "%'";
		}
		if (!this.isNull(provice)) {

			hql += " and e.provice like '%" + provice + "%'";
		}
		if (!this.isNull(city)) {

			hql += " and e.city like '%" + city + "%'";
		}
		if (!this.isNull(name)) {

			hql += " and e.name like '%" + name + "%'";
		}
		if (!this.isNull(add_admin_id)) {

			hql += " and e.adminByAddAdminId.id='" + add_admin_id + "'";
		}
		if (!this.isNull(order_type)) {

			String arr[] = order_type.split("_");
			hql += " order by e." + arr[0] + " " + arr[1];
			hql += ",e.addtime desc";
		} else {
			hql += " e.addtime desc";
		}
	
		



这样写可不可以??
为什么很多人用StringBuffer的..???

你可以去试下,StringBuffer的效率不是String能比的,拼接的时候String多了严重影响性能。当然,如果就几条那也没什么,不过强烈推荐不要用String,不是个好习惯。


我记得有帖子说过jdk1.5以后对字符串相加做了优化,效率和StringBuffer一样了啊,我没做过实验,谁做过实验的来说两句

在编译的时候,确实会适时的将字符串拼接转成StringBuilder

别信任何jvm作出的承诺
比如线程优先级
比如某string池的优化
比如string可以自己用buffer解析
50 楼 qchong 2010-07-13  
ywlqi 写道
Das_flamen 写道
superyang 写道
抛出异常的爱 写道
 
StringBuffer buffer = new StringBuffer("select * from T where 1=1 ");
for(Map.Enty e : map){
    buffer .appand ("and "+ e.getKey()+" = '"+e.getValue()+"'");
}




		String hql = "select e.id,e.name,e.provice,e.city,e.total,date_format(e.addtime,'%Y-%m-%d'),a.name,date_format(e.sendtime,'%Y-%m-%d') from email e,admin a where e.add_admin_id=a.id";

		if (!this.isNull(email_type)) {

			hql += " and e.name like '%" + email_type + "%'";
		}
		if (!this.isNull(provice)) {

			hql += " and e.provice like '%" + provice + "%'";
		}
		if (!this.isNull(city)) {

			hql += " and e.city like '%" + city + "%'";
		}
		if (!this.isNull(name)) {

			hql += " and e.name like '%" + name + "%'";
		}
		if (!this.isNull(add_admin_id)) {

			hql += " and e.adminByAddAdminId.id='" + add_admin_id + "'";
		}
		if (!this.isNull(order_type)) {

			String arr[] = order_type.split("_");
			hql += " order by e." + arr[0] + " " + arr[1];
			hql += ",e.addtime desc";
		} else {
			hql += " e.addtime desc";
		}
	
		



这样写可不可以??
为什么很多人用StringBuffer的..???

你可以去试下,StringBuffer的效率不是String能比的,拼接的时候String多了严重影响性能。当然,如果就几条那也没什么,不过强烈推荐不要用String,不是个好习惯。


我记得有帖子说过jdk1.5以后对字符串相加做了优化,效率和StringBuffer一样了啊,我没做过实验,谁做过实验的来说两句

在编译的时候,确实会适时的将字符串拼接转成StringBuilder
49 楼 captmjc 2010-07-13  
JE帐号 写道
看了LZ给的图,发现是MS SQL Server,而且是2000...
又是一个不能用sql2000的理由,

+1, MySQL下应该没有差别

lz可以看看select * from table where 1 != 1的速度,如果sql2000真的如此之傻,回去扫描...

2005好像优化的
48 楼 lucane 2010-07-12  
通用查询SQL几乎全是这么干的。。。
47 楼 srdrm 2010-07-12  
这么简单的问题居然争论这么多
46 楼 JE帐号 2010-07-12  
看了LZ给的图,发现是MS SQL Server,而且是2000...
又是一个不能用sql2000的理由,
45 楼 laonao 2010-07-12  
应该对效率没多大的影响
44 楼 xiangkun 2010-07-12  
无语了....
43 楼 jacki6 2010-07-12  
。。。。。。。。。。。。where 1=1 会做优化吗?就单纯这个条件?
42 楼 ywlqi 2010-07-12  
Das_flamen 写道
superyang 写道
抛出异常的爱 写道
 
StringBuffer buffer = new StringBuffer("select * from T where 1=1 ");
for(Map.Enty e : map){
    buffer .appand ("and "+ e.getKey()+" = '"+e.getValue()+"'");
}




		String hql = "select e.id,e.name,e.provice,e.city,e.total,date_format(e.addtime,'%Y-%m-%d'),a.name,date_format(e.sendtime,'%Y-%m-%d') from email e,admin a where e.add_admin_id=a.id";

		if (!this.isNull(email_type)) {

			hql += " and e.name like '%" + email_type + "%'";
		}
		if (!this.isNull(provice)) {

			hql += " and e.provice like '%" + provice + "%'";
		}
		if (!this.isNull(city)) {

			hql += " and e.city like '%" + city + "%'";
		}
		if (!this.isNull(name)) {

			hql += " and e.name like '%" + name + "%'";
		}
		if (!this.isNull(add_admin_id)) {

			hql += " and e.adminByAddAdminId.id='" + add_admin_id + "'";
		}
		if (!this.isNull(order_type)) {

			String arr[] = order_type.split("_");
			hql += " order by e." + arr[0] + " " + arr[1];
			hql += ",e.addtime desc";
		} else {
			hql += " e.addtime desc";
		}
	
		



这样写可不可以??
为什么很多人用StringBuffer的..???

你可以去试下,StringBuffer的效率不是String能比的,拼接的时候String多了严重影响性能。当然,如果就几条那也没什么,不过强烈推荐不要用String,不是个好习惯。


我记得有帖子说过jdk1.5以后对字符串相加做了优化,效率和StringBuffer一样了啊,我没做过实验,谁做过实验的来说两句

相关推荐

    海量数据处理

    在 WHERE 子句中直接使用 `IS NULL` 或 `IS NOT NULL` 进行判断会导致数据库引擎放弃使用索引而执行全表扫描,这在大数据量的情况下极为低效。例如: ```sql -- 不推荐的做法 SELECT id FROM t WHERE num IS NULL; ...

    Oracle SQL 性能优化

    - **低效查询**:`SELECT TAB_NAME FROM TABLES WHERE TAB_NAME = (SELECT TAB_NAME FROM TAB_COLUMNS WHERE VERSION = 604) AND DB_VER = (SELECT DB_VER FROM TAB_COLUMNS WHERE VERSION = 604)` - **高效查询**:...

    基于.net_的大数据量SQL_SERVER_系统_数据库和代码_优化方案

    1. **避免全表扫描**:全表扫描意味着数据库引擎需要遍历表中的每一行数据来查找满足条件的记录,这对于大数据量的应用来说是非常低效的。为了减少全表扫描的次数,我们需要充分利用索引的优势。 2. **合理利用索引*...

    查询优化技巧三十则

    SELECT num FROM a WHERE EXISTS (SELECT 1 FROM b WHERE num = a.num); ``` #### 14. 减少字符串操作 在查询条件中过多地使用字符串操作(如 `UPPER`, `LOWER`)可能导致索引无法被利用。 #### 15. 限制返回的...

    处理百万级以上的数据查询提高效率的办法

    SELECT col1, col2 INTO #t FROM t WHERE 1 = 0; ``` - **正确做法**(创建空表): ```sql CREATE TABLE #t (col1 datatype, col2 datatype); ``` #### 12. 优化子查询的使用 子查询可能导致性能下降,特别...

    SQL Server SQL优化

    - **推荐做法**:在可以接受脏读的情况下使用`WITH (NOLOCK)`,如`SELECT TOP 1 * FROM A WITH (NOLOCK) WHERE state = 1`。 - **不推荐做法**:直接使用`SELECT TOP 1 * FROM A WHERE state = 1`,可能导致长时间...

    数据查询优化技巧三十则

    10. **避免无用的查询结构**:如`SELECT col1, col2 INTO #t FROM t WHERE 1 = 0;`这类查询不返回任何行,但会浪费系统资源。 11. **使用`EXISTS`代替`IN`**:在大多数情况下,`EXISTS`比`IN`更高效,因为`EXISTS`...

    Oracle SQL性能优化技巧总结

    如果`tab1`作为基础表,则需要对所有记录进行处理,这显然是低效的。 - 高效示例: ```sql SELECT COUNT(*) FROM tab1, tab2; ``` 将记录数较少的`tab2`作为基础表,可以显著提高查询速度。 - **扩展**:当...

    数据库查询效率

    - **优化技巧**:对于连续的数值查询,推荐使用BETWEEN替代IN,如 `SELECT id FROM t WHERE num BETWEEN 1 AND 3`。 **5. LIKE操作符的优化** - **问题说明**:使用LIKE进行模式匹配时,特别是前导通配符(如 `%abc...

    Oracle-SQL优化(内部资料).docx

    - 方法1(最低效):分别执行两次查询。 - 方法2(次低效):使用游标执行两次查询。 - 方法3(高效):使用一个查询同时获取所需的信息。 此外,还可以通过调整SQL工具中的ARRAYSIZE参数来增加每次数据库访问的...

    access分页实现 源代码

    SELECT TOP pagesize * FROM table WHERE 1=1 condition sort; ``` 其中`condition`和`sort`会在实际执行时根据传入的参数动态拼接。 2. **非首页面查询**:对于非首页面,查询逻辑相对复杂。首先,需要获取前...

    MySQL性能优化的最佳实践

    SELECT 1 FROM users WHERE username = '中国' LIMIT 1; ``` #### 五、合理使用索引 **4. 为搜索字段建索引** 除了主键和唯一字段外,还可以为经常用于搜索的字段创建索引。例如,如果经常需要按`last_name`字段...

    Java中Oracle操作绑定变量使用用户工具模块解决方案

    StringBuffer sql = new StringBuffer("SELECT id, name, department, leader FROM employee WHERE 1=1"); if (name != null && name.trim().length() &gt; 0) { sql.append(" AND name='" + name.trim() + "'"); } if...

    Mysql查询优化详解(含示例)

    通过分析EXPLAIN的结果,我们可以找出执行计划中的低效部分并进行优化。 #### 二、优化索引 索引是提升查询性能的关键因素之一。合理的索引设计可以显著提高查询速度。下面是一些建议: 1. **确保有合适的索引**...

    经常要用的DB2优化

    - **低效**: `SELECT * FROM EMP WHERE EMPNO &gt; 0 AND DEPTNO IN (SELECT DEPTNO FROM DEPT WHERE LOC = 'MELB')` - **高效**: `SELECT * FROM EMP WHERE EMPNO &gt; 0 AND EXISTS (SELECT 'X' FROM DEPT WHERE DEPT....

    Oracle数据库中分页查询介绍

    由于Web应用的无状态特性,每个请求都是独立的,维持数据库游标以供后续请求是低效的。游标是一种宝贵的资源,应当在每次操作完成后关闭。 Oracle数据库不支持通过行集(rowset)向后移动游标,这意味着一旦用户向前...

    SQL优化 SQL 优化

    **1. 选用适合的Oracle优化器** Oracle数据库支持多种优化器模式: - **基于成本(Cost)**:默认模式,基于统计信息估算查询成本。 - **基于规则(Rule)**:较老的优化策略,适用于特定场景。 - **选择性(Choose...

Global site tag (gtag.js) - Google Analytics