SELECT [Id],[GroupId],[Name],[Password],[Email],[Phone],[CreditCard],[Education],[Address] FROM [Users] WHERE [Id] IN (SELECT [Id] FROM (SELECT [RK] = ROW_NUMBER() OVER(PARTITION BY [GroupId] ORDER BY [Id] DESC),[Id] FROM [Users]) AS t WHERE t.[RK] <= 10) ORDER BY [GroupId]
主键id,索引groupid
以上sql 在150w数据 查询时间2s
各位看官可有更优化的方案
目测没有,马克
子查询后left join目测比in更快。还有你的业务允许脏读吗?加上WITH(NOLOCK)在特定条件下有性能提升。
有一些提升,但是微乎其微
尽量不要用 in 和not in 很影响效率的,可以改为 exists 和not exists
SELECT [Id],[GroupId],[Name],[Password],[Email],[Phone],[CreditCard],[Education],[Address] FROM [Users] as u WHERE
Exists (SELECT 1 FROM (SELECT [RK] = ROW_NUMBER() OVER(PARTITION BY [GroupId] ORDER BY [Id] DESC),[Id] FROM [Users]) AS t
WHERE t.[RK] <= 10 AND t.[Id]=u.[Id]) ORDER BY [GroupId]
性能损失都在排序上面
in查询影响比较小,优化后能少几十毫秒
可以试试将子查询改成左表,然后join 你的Users表,而且,貌似不需要用row_number吧。
declare @MaxGroupId int select top 10 @MaxGroupId = [GroupId] from [Users] group by [GroupId] order by [GroupId] DESC SELECT [Id],[GroupId],[Name],[Password],[Email],[Phone],[CreditCard],[Education],[Address] FROM [Users] WHERE [GroupId] >= @MaxGroupId
抱歉,没看仔细,以上代码更改了题意。
你的两个表都是User表,为什么还要去in一次呢?直接在子查询里面多查询几个字段就好了哇。
@幻天芒: 子查询字段越多越慢,因为全表扫描了,分区跟ROW_NUMBER()都是全表的,只查主键是最快的
@FClouds: 那就把in去掉,把你子查询的结果用来做主表(左表),关联(inner join)Users表做查询
left join会更快,in 的话尽量别用