大数据量排序问题 ORDER BY 大家有没有遇到过

时间:2021-09-07 20:03:14
SELECT top(10) A.ClientId,A.InvStatus, A.OnCurrent, A.ModifyDate ,A.InstallDate as InstallDate2 
FROM II_InstallSW A 
WHERE  A.ModifyDate >= '2009-05-11 00:00:00' AND A.ModifyDate <= '2009-08-11 23:59:59' 
order by InstallDate2 asc 

数据量 600~1000万左右。

由于检索需要现有索引3个
CREATE CLUSTERED INDEX [IDX_01] ON [dbo].[II_InstallSW] 
(
       [ClientId] ASC,
       [ModifyDate] ASC,
       [OnCurrent] ASC
)

CREATE NONCLUSTERED INDEX [IDX_2] ON [dbo].[II_InstallSW] 
(
       [ClientId] ASC,
       [PackageId] ASC
)

CREATE NONCLUSTERED INDEX [IDX_3] ON [dbo].[II_InstallSW] 
(
       [ModifyDate] ASC,
       [PackageId] ASC
)

系统的title可以点击 点击后按照该字段排序显示 ,也就是说按照什么排序 不一定
点击其他几个字段还都好 和已有的索引沾边 大概都用上索引了 速度可以
就是点击
InstallDate,InvStatus排序的时候可能是由于没有相关索引 速度很慢 结果出不来

像这样动态变化的order by 大家都怎么处理的呀

给每个字段都单独建上索引是不可能的  因为程序里所有的页面都可以这样选择排序方式 难道要吧每个表每个字段都建立索引呀

35 个解决方案

#1


建议使用分区表试试

#2


declare @s datetime ,@s2 datetime
set @s='2009-05-11 00:00:00'
set @s2='2009-08-11 23:59:59' 
SELECT top(10) A.ClientId,A.InvStatus, A.OnCurrent, A.ModifyDate ,A.InstallDate as InstallDate2 
FROM II_InstallSW A 
WHERE  A.ModifyDate between @s and @s2
order by InstallDate2 asc 

改为变量 试试

我好想哪里看到过 这个变为变量放到条件加快。也许是减慢 你去试试吧 
执行计划CTRL+L 看看就知道了 。。

#3


引用 1 楼 pt1314917 的回复:
建议使用分区表试试

UP下

#4


引用 1 楼 pt1314917 的回复:
建议使用分区表试试


用分区表吧  数据量在600-1000W已经比较大了

#5


改为between  and
会快点吧 

#6


就是点击 
InstallDate,InvStatus排序的时候可能是由于没有相关索引 速度很慢 结果出不来 

那你应该可以判断是点了哪个,再用动态执行,ORDER BY 点击的那个

#7


如果不是很多的话,用if也可以啊

declare @order varchar(4000)
set @order=''

if 条件1 and @order<>''
    @order = 'select * from ta order by '+@order
if 条件2 and @order<>''

。。。。

    exec(@order)

#8


BETWEEN .......AND ..已经很快了

#9


引用 2 楼 feixianxxx 的回复:
SQL codedeclare@sdatetime ,@s2datetimeset@s='2009-05-11 00:00:00'set@s2='2009-08-11 23:59:59'SELECTtop(10) A.ClientId,A.InvStatus, A.OnCurrent, A.ModifyDate ,A.InstallDateas InstallDate2FROM II_InstallSW AWHERE  A.ModifyDatebetween@sand@s2orderby InstallDate2asc
改为变量 试试

我好想哪里看到过 这个变为变量放到条件加快。也许是减慢 你去试试吧
执行计划CTRL+L 看看就知道了 。。

刚试验了一下  好像效果不太明显

#10


between  and 也试了 还是不行 
分区表 还不太熟悉 

#11


SELECT top(10) A.ClientId,A.InvStatus, A.OnCurrent, A.ModifyDate ,A.InstallDate as InstallDate2 
FROM II_InstallSW A 
WHERE  A.ModifyDate >= '2009-05-11 00:00:00' AND A.ModifyDate <= '2009-08-11 23:59:59' 
order by InstallDate2 asc 

建议楼主用动态连接成SQL,排序字段用变量来表示,用参数来传递排序字段

#12


建议 使用临时表

#13


引用 11 楼 sql77 的回复:
SQL codeSELECTtop(10) A.ClientId,A.InvStatus, A.OnCurrent, A.ModifyDate ,A.InstallDateas InstallDate2FROM II_InstallSW AWHERE  A.ModifyDate>='2009-05-11 00:00:00'AND A.ModifyDate<='2009-08-11 23:59:59'orderby InstallDate2asc
建议楼主用动态连接成SQL,排序字段用变量来表示,用参数来传递排序字段

是说order by 的内容用变量代替么  这样应该不会让速度加快特别多吧

#14


刚才看了一下分区表的东西 好像是挺好  但是这个划分是要改变表结构么? 
现在来讲最好还是不改表结构,客户那边的原因

#15


引用 14 楼 n688com 的回复:
刚才看了一下分区表的东西 好像是挺好  但是这个划分是要改变表结构么?
现在来讲最好还是不改表结构,客户那边的原因


分区表不改变表结构

#16


引用 13 楼 n688com 的回复:
引用 11 楼 sql77 的回复:
SQL codeSELECTtop(10) A.ClientId,A.InvStatus, A.OnCurrent, A.ModifyDate ,A.InstallDateas InstallDate2FROM II_InstallSW AWHERE  A.ModifyDate>='2009-05-11 00:00:00'AND A.ModifyDate <='2009-08-11 23:59:59'orderby InstallDate2asc
建议楼主用动态连接成SQL,排序字段用变量来表示,用参数来传递排序字段

是说order by 的内容用变量代替么  这样应该不会让速度加快特别多吧

分区表应该是一个好选择,
那你不是在字段上都建立了索引了吗

#17


数据量 600~1000万左右。 sqlserver索引搞不定的,只能分表了

#18


分区表是不改变表结构 只不过存储时候 存到不同的地方么?
那应该按照什么分呢
这个表里存的数据是5万人的PC中安装的所有软件

#19


引用 18 楼 n688com 的回复:
分区表是不改变表结构 只不过存储时候 存到不同的地方么?
那应该按照什么分呢
这个表里存的数据是5万人的PC中安装的所有软件

http://topic.csdn.net/u/20090810/14/24fb72f2-af40-4fd9-9ebd-9957ff2041f7.html
看这个帖子 上面有高人回答 分区表的东西

#20


我先去拜读一下
另外如果是索引的话应该建立什么的
CREATE NONCLUSTERED INDEX [IDX_3] ON [dbo].[II_InstallSW] 
(     [ModifyDate] ASC,
      [InstallDateas]  asc 
)

这样?建立一个测试 没什么改善呢?

#21


没怎么看明白,再看看先

#22


google,baidu上找找

#23


关键是排序,

如果选择到的数据不多,可以考虑查询时不排序,在客户端处理排序,好多控件都有sort方法

#24


恩 feixianxxx 兄的帖子真是不错 学习了 —— 你咋不结贴呢 这顿看啊 呵呵

#25


数据比较多的 我说的数据量600~1000万是指查询出来的数据(因为ModifyDate得时间比较集中)

#26


引用 20 楼 n688com 的回复:
我先去拜读一下
另外如果是索引的话应该建立什么的
CREATE NONCLUSTERED INDEX [IDX_3] ON [dbo].[II_InstallSW]
(    [ModifyDate] ASC,
      [InstallDateas]  asc
)

这样?建立一个测试 没什么改善呢?

楼主 一般应该是建立聚集索引,效率好点

#27


按ModifyDate建聚集索引试一下,这样可以避免全表扫描

#28


引用 24 楼 n688com 的回复:
恩 feixianxxx 兄的帖子真是不错 学习了 —— 你咋不结贴呢 这顿看啊 呵呵

我懂了就结了

#29


CREATE NONCLUSTERED INDEX [IDX_3] ON [dbo].[II_InstallSW] 
(    [InstallDateas] ASC, 
      [ModifyDate]  asc 


把两个字段换位置就好了
索引生效

恩 由于不能建立聚集 所以只能非聚集了

#30


分区索引 对于分区键 还有些不明确
不知道用什么好 时间好象不行 因为我的时间比较集中 还会把数据存在一个分区中
user不知道怎么样 用user的话我经常会在所有用户中搜索的 就是说要在所有分区中查找 不知道效率如何

#31


对表进行拆分吧
将其分为多个表分别查询再将结果合并。

另:无用的排序建议不要 

#32


1000W的数据,对于SQL的普通表来讲,已经负担很重了。
如果还要频繁的读取数据,那么效果就更差了。
所以,建议楼主用分区表。
索引在这个时候不会起到明显的作用。

如果针对时间字段的排序,数据量比较大,那么最好为分区表。

#33


恩 也是在考虑分区表  但是我这里的数据并不是根据时间平均分配的
可能1000万数据里 有900w 数据集中在一个时间段上 那样分区的结果是 900W数据分到一个分区中 其他分区只有很少数据 似乎失去了分区表的意义了

#34


关注..

#35


引用 23 楼 haiwer 的回复:
关键是排序,

如果选择到的数据不多,可以考虑查询时不排序,在客户端处理排序,好多控件都有sort方法


你选的数据不对,客户端排序有什么用,难道你要把所有数据都拿出来

#1


建议使用分区表试试

#2


declare @s datetime ,@s2 datetime
set @s='2009-05-11 00:00:00'
set @s2='2009-08-11 23:59:59' 
SELECT top(10) A.ClientId,A.InvStatus, A.OnCurrent, A.ModifyDate ,A.InstallDate as InstallDate2 
FROM II_InstallSW A 
WHERE  A.ModifyDate between @s and @s2
order by InstallDate2 asc 

改为变量 试试

我好想哪里看到过 这个变为变量放到条件加快。也许是减慢 你去试试吧 
执行计划CTRL+L 看看就知道了 。。

#3


引用 1 楼 pt1314917 的回复:
建议使用分区表试试

UP下

#4


引用 1 楼 pt1314917 的回复:
建议使用分区表试试


用分区表吧  数据量在600-1000W已经比较大了

#5


改为between  and
会快点吧 

#6


就是点击 
InstallDate,InvStatus排序的时候可能是由于没有相关索引 速度很慢 结果出不来 

那你应该可以判断是点了哪个,再用动态执行,ORDER BY 点击的那个

#7


如果不是很多的话,用if也可以啊

declare @order varchar(4000)
set @order=''

if 条件1 and @order<>''
    @order = 'select * from ta order by '+@order
if 条件2 and @order<>''

。。。。

    exec(@order)

#8


BETWEEN .......AND ..已经很快了

#9


引用 2 楼 feixianxxx 的回复:
SQL codedeclare@sdatetime ,@s2datetimeset@s='2009-05-11 00:00:00'set@s2='2009-08-11 23:59:59'SELECTtop(10) A.ClientId,A.InvStatus, A.OnCurrent, A.ModifyDate ,A.InstallDateas InstallDate2FROM II_InstallSW AWHERE  A.ModifyDatebetween@sand@s2orderby InstallDate2asc
改为变量 试试

我好想哪里看到过 这个变为变量放到条件加快。也许是减慢 你去试试吧
执行计划CTRL+L 看看就知道了 。。

刚试验了一下  好像效果不太明显

#10


between  and 也试了 还是不行 
分区表 还不太熟悉 

#11


SELECT top(10) A.ClientId,A.InvStatus, A.OnCurrent, A.ModifyDate ,A.InstallDate as InstallDate2 
FROM II_InstallSW A 
WHERE  A.ModifyDate >= '2009-05-11 00:00:00' AND A.ModifyDate <= '2009-08-11 23:59:59' 
order by InstallDate2 asc 

建议楼主用动态连接成SQL,排序字段用变量来表示,用参数来传递排序字段

#12


建议 使用临时表

#13


引用 11 楼 sql77 的回复:
SQL codeSELECTtop(10) A.ClientId,A.InvStatus, A.OnCurrent, A.ModifyDate ,A.InstallDateas InstallDate2FROM II_InstallSW AWHERE  A.ModifyDate>='2009-05-11 00:00:00'AND A.ModifyDate<='2009-08-11 23:59:59'orderby InstallDate2asc
建议楼主用动态连接成SQL,排序字段用变量来表示,用参数来传递排序字段

是说order by 的内容用变量代替么  这样应该不会让速度加快特别多吧

#14


刚才看了一下分区表的东西 好像是挺好  但是这个划分是要改变表结构么? 
现在来讲最好还是不改表结构,客户那边的原因

#15


引用 14 楼 n688com 的回复:
刚才看了一下分区表的东西 好像是挺好  但是这个划分是要改变表结构么?
现在来讲最好还是不改表结构,客户那边的原因


分区表不改变表结构

#16


引用 13 楼 n688com 的回复:
引用 11 楼 sql77 的回复:
SQL codeSELECTtop(10) A.ClientId,A.InvStatus, A.OnCurrent, A.ModifyDate ,A.InstallDateas InstallDate2FROM II_InstallSW AWHERE  A.ModifyDate>='2009-05-11 00:00:00'AND A.ModifyDate <='2009-08-11 23:59:59'orderby InstallDate2asc
建议楼主用动态连接成SQL,排序字段用变量来表示,用参数来传递排序字段

是说order by 的内容用变量代替么  这样应该不会让速度加快特别多吧

分区表应该是一个好选择,
那你不是在字段上都建立了索引了吗

#17


数据量 600~1000万左右。 sqlserver索引搞不定的,只能分表了

#18


分区表是不改变表结构 只不过存储时候 存到不同的地方么?
那应该按照什么分呢
这个表里存的数据是5万人的PC中安装的所有软件

#19


引用 18 楼 n688com 的回复:
分区表是不改变表结构 只不过存储时候 存到不同的地方么?
那应该按照什么分呢
这个表里存的数据是5万人的PC中安装的所有软件

http://topic.csdn.net/u/20090810/14/24fb72f2-af40-4fd9-9ebd-9957ff2041f7.html
看这个帖子 上面有高人回答 分区表的东西

#20


我先去拜读一下
另外如果是索引的话应该建立什么的
CREATE NONCLUSTERED INDEX [IDX_3] ON [dbo].[II_InstallSW] 
(     [ModifyDate] ASC,
      [InstallDateas]  asc 
)

这样?建立一个测试 没什么改善呢?

#21


没怎么看明白,再看看先

#22


google,baidu上找找

#23


关键是排序,

如果选择到的数据不多,可以考虑查询时不排序,在客户端处理排序,好多控件都有sort方法

#24


恩 feixianxxx 兄的帖子真是不错 学习了 —— 你咋不结贴呢 这顿看啊 呵呵

#25


数据比较多的 我说的数据量600~1000万是指查询出来的数据(因为ModifyDate得时间比较集中)

#26


引用 20 楼 n688com 的回复:
我先去拜读一下
另外如果是索引的话应该建立什么的
CREATE NONCLUSTERED INDEX [IDX_3] ON [dbo].[II_InstallSW]
(    [ModifyDate] ASC,
      [InstallDateas]  asc
)

这样?建立一个测试 没什么改善呢?

楼主 一般应该是建立聚集索引,效率好点

#27


按ModifyDate建聚集索引试一下,这样可以避免全表扫描

#28


引用 24 楼 n688com 的回复:
恩 feixianxxx 兄的帖子真是不错 学习了 —— 你咋不结贴呢 这顿看啊 呵呵

我懂了就结了

#29


CREATE NONCLUSTERED INDEX [IDX_3] ON [dbo].[II_InstallSW] 
(    [InstallDateas] ASC, 
      [ModifyDate]  asc 


把两个字段换位置就好了
索引生效

恩 由于不能建立聚集 所以只能非聚集了

#30


分区索引 对于分区键 还有些不明确
不知道用什么好 时间好象不行 因为我的时间比较集中 还会把数据存在一个分区中
user不知道怎么样 用user的话我经常会在所有用户中搜索的 就是说要在所有分区中查找 不知道效率如何

#31


对表进行拆分吧
将其分为多个表分别查询再将结果合并。

另:无用的排序建议不要 

#32


1000W的数据,对于SQL的普通表来讲,已经负担很重了。
如果还要频繁的读取数据,那么效果就更差了。
所以,建议楼主用分区表。
索引在这个时候不会起到明显的作用。

如果针对时间字段的排序,数据量比较大,那么最好为分区表。

#33


恩 也是在考虑分区表  但是我这里的数据并不是根据时间平均分配的
可能1000万数据里 有900w 数据集中在一个时间段上 那样分区的结果是 900W数据分到一个分区中 其他分区只有很少数据 似乎失去了分区表的意义了

#34


关注..

#35


引用 23 楼 haiwer 的回复:
关键是排序,

如果选择到的数据不多,可以考虑查询时不排序,在客户端处理排序,好多控件都有sort方法


你选的数据不对,客户端排序有什么用,难道你要把所有数据都拿出来