1,SELECT * FROM news WHERE TYPE IN (SELECT id FROM classify WHERE type='2')2,SELECT n.* FROM news n,classify c WHERE c.id=n.type AND c.type='2'
最好能说个理由,今天同事们为了这两个语句辩论了整整一中午了噶
下班前结贴,谢谢大虾们赐教
最好能说个理由,今天同事们为了这两个语句辩论了整整一中午了噶
下班前结贴,谢谢大虾们赐教
解决方案 »
- 执行set names gbk;数据库端出现警告事件?
- 检查数据表中某个变量字段是否存在。
- MySQL自定义函数中要删除表怎么处理?
- 虚心求教一个mysql的语句写法
- 继续在在 问个MYSQL 时间方面的问题。
- 跪求解答!郁闷几天了,一个关于MySQL C API 的问题。
- mysql启动时可否修改端口号?如执行mysqld -??
- 菜菜鸟提问,有关mysql与php
- 请教:关于 MySQL 和 MySQL JDBC 的问题。
- 银行存款的事务一般是怎样实现的?是否分布式?事务如何控制
- MySQL启动时InnoDB报一些错误,这个怎么解决
- ./bin/my_print_defaults: cannot execute binary file
/*==============================================================*/
/* Table: classify [分类表] */
/*==============================================================*/
create table classify
(
id varchar(25) not null, -- 编号
name varchar(80), -- 名称
type char(1), -- 类型
primary key (id)
)
type = InnoDB;/*==============================================================*/
/* Table: news [新闻表] */
/*==============================================================*/
create table news
(
id varchar(25) not null, -- 编号
type varchar(25), -- 分类,对应classify表ID
title varchar(100), -- 标题
primary key (id)
)
type = InnoDB;数据库表没有设置外键,是用程序控制的!
show profiles
show profile for query 1;
在classify上建立id、type联合索引
news上建立type索引
实际上你自己测试 一下,看看执行时间就判断出来了
2. 每个表中的数据情况,每个表中的记录总数是多少?如果两个表中都只有10条记录,则没什么差别,所有记录都可以在内存中搞定。
在SQL 2005中 ,第二条语句
SELECT n.* FROM news n,classify c WHERE c.id=n.type AND c.type='2'
表news有聚集索引但是查询中没有用到news.id因此对于表news做了一个聚集所以扫描运算,相反对classify表做了一个聚集索引查找运算,然后再进行嵌套循环
第一条查询也是一样的分析,所以效率都是一样的。
因为都从WHERE 开始遍历表。
两张表都遍历了一次
差不多吧第一个先执行子查询第二个先执行c.type='2',再执行连接这样2个理论上就差不多了
http://topic.csdn.net/u/20090626/16/65f043cf-b9d9-4707-b660-9857461177f4.html
SELECT * FROM news WHERE TYPE IN (SELECT id FROM classify WHERE type='2')
等同于
where id=a1 or id=a2 or id=a3......
先找出集合然后再一个一个比较SELECT n.* FROM news n,classify c WHERE c.id=n.type AND c.type='2'
这个貌似n和c进行个运算就出来了(线代忘干净了)
代表理由:(1)select执行笛卡尔积和投影操作会影响效率,第一句层次分明易于理解
(2)《数据库系统概论第四版》提到过(未考证)
代表者:64楼 luoweihua7
65楼 gangqinjiawang2,第二种方法优
代表理由:(1)数据量大时IN的效率不高
(2)第二种用到了索引id
代表者:47楼 zhan7505201
58楼 afandasan
15楼 ssp2009 等等3,两种方法一样
代表理由:(1)SQL计划执行,会自动选择最优的SQL语句执行
(2)表news有聚集索引但是查询中没有用到news.id因此对于表news做了一个聚集所以扫描运算,相反对classify表做了一个聚集索引查找运算,然后再进行嵌套循环
第一条查询也是一样的分析,所以效率都是一样的。 代表者:26楼 winner2050
30楼 bala7229291
支持者数量统计: 第一种优:2人
第二种优:9人
两种一样:8人 对比:第二种 > 一样 > 第一种
再次申明,两个表除了主键索引外再没有任何索引欢迎大家发表自己独到的观点,继续讨论
SELECT * FROM news WHERE TYPE IN (SELECT id FROM classify WHERE type='2')
如果classify表随着时间增大,子查询遍历出来的结果会很多。再用主查询一一遍历子查询的结果。效率很低。第二条:
SELECT n.* FROM news n,classify c WHERE c.id=n.type AND c.type='2'
可以看到,where中将 c.id=n.type 做了联接。 可以看成将2个表合并为一个大表做查询。
每条记录判定1次。效率明显要比前一个不停的用得到的条件遍历同一个表效率高。浅见。可能很多地方欠考虑
IN 的作用相当与OR
语句:
Select * from table1 where tid in (2,3)
和
Select * from table1 where tid=2 or tid=3
是一样的,都会引起全表扫描,如果tid上有索引,其索引也会失效。
是不是in的速度慢呢。
还有就是测试,每次测试时运行的时间不是固定的。我对于同一个查询进行反复运行,得出的时间都不固定,且与运行先后无关。差距可达到20%。
步骤1:首先SELECT id FROM classify WHERE type='2'
表有主键,即聚集索引,采用聚集索引扫描,然后把扫描出的type=2的所有 行,取出id
步骤2:然后用查询的id作为type谓词的值进行SELECT * FROM news WHERE TYPE =id
表有主键,即聚集索引,采用聚集索引扫描,逐一进行type与id的匹配(连接)查询计划2:
步骤1:首先SELECT id FROM classify WHERE type='2'
放弃使用聚集索引扫描,而使用行扫描,匹配type=2的所有行,取出id
步骤2:然后用查询的id作为type谓词的值进行SELECT * FROM news WHERE TYPE =id
放弃使用聚集索引扫描,而使用行扫描,逐一进行type与id的匹配(连接)查询计划3:
步骤1:首先SELECT * FROM news 的查询
表有主键,即聚集索引,采用聚集索引扫描,取出type
步骤2:SELECT id FROM classify WHERE id=(n.type) and type='2'
表有主键,谓词使用主键,采用聚集索引查找,然后连接
.................其实还有几种组合,至少我知道的因为扫描一般是比查找慢,聚集索引>索引>堆(行):所以从效率上来说
聚集索引查找>索引查找>聚集索引扫描>索引扫描>行扫描(表扫描)查询计划3是最优的,有兴趣的可以分析一下第二个查询,得到最优的结果也是这里的查询计划3
所以两条语句在执行的时候是一样的效率。另外在优化查询计划的时候,语句一可能比语句而消耗略微多一点,但是跟查询时间比不是一个数量级的(因为基于优化的时间是相当昂贵的,如果时间过多,不如不做优化) 所以总的来说两条的效率是一样的,非要比个高低,也许第二条略微有点优势。进一步的话,可以通过设置type为索引,查询的计划就变为:聚集索引查找+索引查找+连接 这样就优化了
我还想到一种写法不知道效果如何
select n.* from (SELECT id FROM classify WHERE type='2') c left join news n on c.id=n.type
比如用 .Net 命名空间 来存放跟网络有关的的业务处理 大体的有Send(),Receive(),Status()
用.UI 命名空间来存放界面显示的业务
访问网络的时候调用.Net 下面的 那三个方法 就可以搞定的