是谁说的in不走索引?!

wzp144650 2011-12-29 03:16:07
从接触数据那天开始就听周围的大神们说,不要用in,in不走索引!

直到后来我知道了什么是执行计划,我自己做测试,执行计划上清清楚楚的写着 index seek,有次面试还被问我,我就告诉他“很多人都说in不走,但是我自己测试它是走的,所以我的回答是走索引”,他问我怎么知道的,我说看的执行计划。

正好今天又遇到in正好做了一个测试,现将测试结果发上来,我想看看为什么这么多人说in不走索引。



/**************Script 2************************************/
use tempdb
go
if exists (select * from dbo.sysobjects where id = object_id(N'[tbl1]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [tbl1]
GO
create table tbl1
(学生号 int,学生姓名 varchar(20),性别 char(2), 年龄 int,入学时间 datetime,备注 char(500))
go
declare @i int
set @i=0
declare @j int
set @j=0
while @i<5000
begin
if (rand()*10>3) set @j=1 else set @j=0
insert into tbl1 values(@i,
char( rand()*10+100)+char( rand()*5+50)+char( rand()*3+100)+char( rand()*6+80),
@j, 20+rand()*10,convert(varchar(20), getdate()-rand()*3000,112),
char( rand()*9+100)+char( rand()*4+50)+char( rand()*2+130)+char( rand()*5+70))
set @i=@i+1
end
/**************************************************/


create nonclustered index idx_学生姓名 on tbl1(学生姓名)

/******Script 5***********************************/
set statistics profile on
set statistics io on
go
select 学生姓名 from tbl1 where 学生姓名 in ('d2dP','d2dQ')

go
set statistics profile off
set statistics io off
/*************************************************/


rows executes stmttext
18 1 select 学生姓名 from tbl1 where 学生姓名 in ('d2dP','d2dQ')
18 1 |--Index Seek(OBJECT:([tempdb].[dbo].[tbl1].[idx_学生姓名]), SEEK:([tempdb].[dbo].[tbl1].[学生姓名]='d2dP' OR [tempdb].[dbo].[tbl1].[学生姓名]='d2dQ') ORDERED FORWARD)
...全文
2854 37 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
37 条回复
切换为时间正序
请发表友善的回复…
发表回复
无聊找乐 2012-01-07
  • 打赏
  • 举报
回复
in不走索引是指in里面的内容,不是指含有in关键字的sql语句。
你那个in里面的数据集原本就可以是任意随机的一个数据集合,怎么可能有索引。
你的测试结果没有表现出明显的性能下降只是因为你in的数据很少。
索引在少量数据的情况下本身就体现不出什么性能提升。
你试一下in(datasource),datasource包含万条以上的数据看看。
flysworde 2012-01-07
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 cacoda 的回复:]
传说中IN效率低,事实上不是,看看SQLServer的分页问题,不用In都没法干。
[/Quote]
完全可以的,
create PROCEDURE [dbo].[proPagination]
(
@TableName nvarchar(200)
,@OrderBy nvarchar(200) = ' id '
,@FieldList nvarchar(500) = '*'
,@Filter nvarchar(1000)
,@StartIndex int = 1
,@PageSize int = 1
)
AS
BEGIN
SET NOCOUNT ON
DECLARE @ExecSql nvarchar(max) -- 要执行的ql
DECLARE @where varchar(max)
DECLARE @EndIndex int

SET @EndIndex = @startIndex+@pageSize-1
if len(@Filter) = 0
set @where = ''
else
set @where =' WHERE '+ @Filter
SET @ExecSql = 'WITH RowList AS ( '
+'SELECT ROW_NUMBER() OVER (ORDER BY '+@OrderBy+' )AS Row, '+ @FieldList
+' from '+@TableName + ' ' + @where +' ) '
+' SELECT ' + @FieldList + ' FROM RowList WHERE Row between '+convert(varchar,@startIndex)+' and '+convert(varchar,@EndIndex)
print @ExecSql
EXEC (@ExecSql) -- 返回结果集
END
这是一个用于分页的存储过程
ekinguofeng 2012-01-06
  • 打赏
  • 举报
回复
索引不是什么列上建,就可以提升查询性能的,以上测试明显有问题,10万零1笔数据中,找出10万笔数据,这都不用建索引了,全表扫描就可以了,好好研究下SQL Server官网上,查询分析器是如何通过索引上的统计信息来自动生成执行计划,你就知道怎么回事了。
conggle 2012-01-06
  • 打赏
  • 举报
回复
看看SQLServer的分页问题,不用In都没法干。
gw6328 2012-01-04
  • 打赏
  • 举报
回复
没有说过不走索引吧。好像听过用exists 代替in的做 但是in还是要走索引啊。
liouse 2012-01-04
  • 打赏
  • 举报
回复
可以测试啊?怎么做测试?
liouse 2012-01-04
  • 打赏
  • 举报
回复
sql 索引 知识。
禁用F3 2012-01-04
  • 打赏
  • 举报
回复
是的,我今天在某群里面也看到说IN不走索引,还要我去补基础知识....但我测试是走索引的,说in不走索引的是很多。搞得我一头雾水,不过还是要相信结果看计划就可以了
农家的牛 2012-01-03
  • 打赏
  • 举报
回复
我还经常用select * from XXXX where AAA in (select AAA from XY where BBB='data')这类的IN在几十万条数据表中进行操作,也不见得速度不行。
代码日志 2012-01-03
  • 打赏
  • 举报
回复
MSSQL优化之————探索MSSQL执行计划
  • 打赏
  • 举报
回复
听大婶们说IN不走索引,后改UNION,最后悲剧了
还好现在改IN 了
yy1987316 2012-01-02
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 zl87242994 的回复:]

听大婶们说IN不走索引,后改UNION,最后悲剧了
还好现在改IN 了
[/Quote]
union是效率杀手
geniuswjt 2011-12-30
  • 打赏
  • 举报
回复
这个还真有办法[Quote=引用 12 楼 cacoda 的回复:]
传说中IN效率低,事实上不是,看看SQLServer的分页问题,不用In都没法干。
[/Quote]
jmx123456789 2011-12-30
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 beirut 的回复:]
我记得是小F说的
[/Quote]

[Quote=引用 4 楼 geniuswjt 的回复:]
我记得小F那个索引总结里是说过in是能走索引的
[/Quote]

chenguang79 2011-12-30
  • 打赏
  • 举报
回复
我记得在SQL server 2005技术内幕里说,in 和exists的执行计划一样.not in比not exists慢.
唉.........
昵称被占用了 2011-12-30
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 qianjin036a 的回复:]
这个故事告诉我们,有些事情不单单要听所谓的"大神们"说,最好自己亲自动手做一做.
[/Quote]
网上的资料,只能当作一个指引,乱的很多,自己不分辨只能是自己责任
水族杰纶 2011-12-30
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 beirut 的回复:]
我记得是小F说的
[/Quote]
Rotel-刘志东 2011-12-30
  • 打赏
  • 举报
回复
实践才是真理。
tyxddgs 2011-12-30
  • 打赏
  • 举报
回复
列 in('a','b')
相当于 列=‘a’or 列=‘b’

所以,只要列建立了索引,而且查询数据时,返回的值不是很大,那么,肯定是走索引的,除非你强制不走索引!
苦苦的潜行者 2011-12-30
  • 打赏
  • 举报
回复
我就看看,我也不懂什么in,也不懂什么叫执行计划.先mark以后在看.
加载更多回复(14)

34,838

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧