关于索引的一道经典面试题

问题:
从100万条记录中的到 成绩最高的记录

问题分析:
要从一张表中找到成绩最高的记录并不难,有很多种办法,最简单的就是利用TOP 1
select   top   1   *   from  student  order   by  score  desc

但是这种方法有一点小问题,就是如果成绩最高的有两个人的话只能查出其中的一个。

对上面的方法进行改进:

select   top   1   with  ties  *   from  student  order   by  score  desc


或用子查询的方式:
select   *   from  student  where  score  = (
select   max (score)  from  student)

select   *   from  student  where  score  =  ( select   top   1  score  from  student  order   by  score  desc )

=================成功的分割线======================
但是这个题目成功与否不在于能否查询出成绩最高的记录,而在于用最快的速度查询出来。经过测试从100万条记录中找到成绩最高的记录如果使用第一个方法需要1秒多,
下面是测试的代码:
我这里创建的表是person,查询的是年龄最大的
代码
create   table  person
(
id 
int   identity ( 1 , 1 not   null ,
pid 
varchar ( 18 not   null ,
md 
varchar ( 11 not   null ,
age 
int
)
go

declare   @pid   varchar ( 15 )
declare   @age   int
declare   @mb   varchar ( 11 )
declare   @count   int
set   @count   =   0
-- 插入100万条随机的记录
while ( @count   <   1000000 )
begin
    
-- 生成随机的PID
     select   @pid = substring ( cast ( rand ()  as   varchar ( 20 )), 3 , 6 ) +
        
substring ( cast ( rand ()  as   varchar ( 20 )), 3 , 6 ) + substring ( cast ( rand ()  as   varchar ( 20 )), 3 , 6 )
    
-- 生成随机的MB
     select   @mb = substring ( cast ( rand ()  as   varchar ( 20 )), 3 , 6 ) +
        
substring ( cast ( rand ()  as   varchar ( 20 )), 3 , 5 )
    
-- 生成随机的AGE
     select   @age   =   cast  ( rand ()  *   100   as   int )
    
-- 将生成的随机数据插入表
     insert   into  person
        
values  (  @pid @mb , @age )

    
set   @count   =   @count   +   1
end  



以上插入的语句需要执行20分钟以上,请耐心等待
完成后用下面的测试看执行的效率

代码

DECLARE   @BD   DATETIME
DECLARE   @ED   DATETIME
SET   @BD   =   GETDATE () -- 执行之前记录时间
SELECT   TOP   1   *   FROM  PERSON   ORDER   BY  AGE  DESC
SET   @ED   =   GETDATE () -- 执行之后记录时间
SELECT   datediff (millisecond, @BD , @ED ) -- 用毫秒的方法显示执行时间。


 



我的电脑执行的时候是在1100-1500之间
如果是用子查询的方式会更慢。大约在5000毫秒左右。

解决办法:
为person表的age这一列创建索引
create   nonclustered   index  ix_age
on  person(age)

公平起见执行一下清空缓存的语句: (感谢 huyg的提醒)

DBCC  FREEPROCCACHE  -- 清空SQL缓存
DBCC  DROPCLEANBUFFERS


创建之后同样运行上面的测试速度的语句,看到的毫秒数是266。
Oh Yeah!效率提高了无数倍。
使用子查询的方式再试试看:
DECLARE   @BD   DATETIME
DECLARE   @ED   DATETIME
SET   @BD   =   GETDATE ()

select   *   from  person  where  age  = (
select   max (age)  from  person )
 
SET   @ED   =   GETDATE ()
SELECT   datediff (millisecond, @BD , @ED )

 

我执行的时间是4186毫秒,效率略有提升。

但是这样查询出的结果是10192条记录。查询结果记录多的原因是结果集数量太大。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是老姚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值