子查询 关联查询 效率问题 [转载]

  子查询就是查询中又嵌套的查询,表连接都可以用子查询,但不是所有子查询都能用表连接替换,子查询比较灵活,方便,形式多样,适合用于作为查询的筛选条件,而表连接更适合与查看多表的数据。


子查询不一定需要两个表有关联字段,而连接查询必须有字段关联(所谓的主外键关系)

  1. 表关联的效率要高于子查询,因为子查询走的是笛卡尔积
  2. 表关联可能有多条记录,子查询只有一条记录,如果需要唯一的列,最好走子查询

 

对于数据量多的肯定是用连接查询快些,原因:因为子查询会多次遍历所有的数据(视你的子查询的层次而定),而连接查询只会遍历一次。

但是数据量少的话也就无所谓是连接查询还是子查询,视自己的习惯而定。一般情况下还是用子查询来的好,容易控制

为什么子查询比连接查询(LEFT JOIN)效率低

MySQL从4.1版本开始支持子查询,使用子查询进行SELECT语句嵌套查询,可以一次完成很多逻辑上需要多个步骤才能完成的SQL操作。子查询虽然很灵活,但是执行效率并不高。
那么问题来了,什么是子查询?为什么它的效率不高?
子查询:把内层查询结果当作外层查询的比较条件

示例:

select goods_id,goods_name from goods where goods_id = (select max(goods_id) from goods);
执行子查询时,MYSQL需要创建临时表,查询完毕后再删除这些临时表,所以,子查询的速度会受到一定的影响,这里多了一个创建和销毁临时表的过程。

优化方式:

可以使用连接查询(JOIN)代替子查询,连接查询不需要建立临时表,因此其速度比子查询快。

子查询和关联查询的效率问题

MSDN对子查询的定义是这样的:

     可以将一个查询的结果用作另一个查询的输入。可以将子查询的结果用作使用 IN( ) 函数、EXISTS 运算符或 FROM 子句的语句。

     一条好的值得称赞的规则是尽量用连接代替所有的子查询。优化器有时可以自动将子查询“扁平化”,并且用常规或外连接代替。但那样也不总是有效。明确的连接对选择表的顺序和找到最可能的计划给出了更多的选项。当你优化一个特殊查询时,了解一下是否去掉自查询可产生很大的差异。这段话出自http://www.innovatedigital.com/htm_speek/SQLServerOpt.shtml它显然告诉我们在查询的时候最好不要用子查询,当时我并不太在意,至到我有一次遇到了这样的情况。  
      
     现在的网站主要的压力都来自于数据库,频繁的数据库访问经常会使服务器死机。我的原则就是尽量减少数据库的连接,能一次性取出的决不多连接数据库一次,但是有时候并不完全是这样。郁闷,无解。    
 
     下面一条SQL语句里面有一个子查询,info.RESOURCE_VOLUMECOUNT,它是指一个电影共有多少集.这个字段是int类型的.子查询的目的就是计算出一个电影在资源表中总共有多少集(实际存在的), 两者做减法操作就可以计算出这个电影共缺多少集(lastCount)我们知道在这条语句执行的时候,外层记录查询一次在计算 lastCount字段的时候又要查询表:电影表一次.如果最外层有10条记录,那么执行这次查询一共要扫描电影表11次,连接数据库1次.
      

    基于有的朋友看不明白我写的SQL语句,可能是因为我写的有些字段和本案例没有太大关系的原因,现在特将它们做一个替换.

 

经过个人实践,证明子查询效率特别低,而一般的子查询都可以由关连查询来实现相同的功能,关联查询的效率要提高很多,所以建议在数据查询时避免使用子查询(尤其是在记录很多时),而最好用关联查询来实现。
      现在举例说明。
     我做的是简单的北京公交查询系统,用的是MySQL数据库,数据库包含两张表,line表和track表。line表有lid和lname两个属性,分别表示线路id和线路名称。track表有lid,seq,sname,lo,la五个属性,分别表示站点所在的线路id,站点在线路上的顺序,站点名称,站点的经度和纬度。现在要查询某一给定线路名称的线路上所有站点的经度和纬度。其中line中有1112条记录,track中约有20万条记录。
     子查询sql语句:select  lo,la  from  track where lid in (select lid from line where lname like '%lname%');
     关联查询sql语句:select lo,la from track,line where line.lname like  '%lname%' and line.lid=track.lid;
     子查询运行时间为5分48秒;而关联查询耗时不足一秒。事实胜于雄辩,关联查询的优势不言而喻。
    在关联查询时要注意:where子句中一定要包含表之间的连接条件,如 line.lid=track.lid,否则查询结果会完全超乎我们的想象,造成不必要的麻烦。   

参考链接:

https://blog.51cto.com/11939767/1911132

https://www.kancloud.cn/limata/xiaonannote/271600

上一篇:SQLZOO答案-Music Tutorial


下一篇:nginx-PHP安装及配置