Joh*_*ant 296 sql sql-server random
我有一个SQL Server表,其中包含大约50,000行.我想随机选择大约5,000行.我想到了一个复杂的方法,创建一个带有"随机数"列的临时表,将我的表复制到其中,循环遍历临时表并用每个行更新RAND()
,然后从该表中选择随机数列< 0.1.我正在寻找一种更简单的方法,如果可能的话,在一个声明中.
本文建议使用该NEWID()
功能.这看起来很有希望,但我看不出如何可靠地选择一定比例的行.
有人曾经这样做过吗?有任何想法吗?
Ral*_*ton 371
select top 10 percent * from [yourtable] order by newid()
Run Code Online (Sandbox Code Playgroud)
回应关于大表的"纯垃圾"评论:你可以这样做以提高性能.
select * from [yourtable] where [yourPk] in
(select top 10 percent [yourPk] from [yourtable] order by newid())
Run Code Online (Sandbox Code Playgroud)
这样做的成本将是对值的关键扫描加上加入成本,在具有较小百分比选择的大型表上应该是合理的.
小智 78
根据您的需求,您TABLESAMPLE
将获得几乎随机和更好的性能.这在MS SQL Server 2005及更高版本上可用.
TABLESAMPLE
将从随机页面而不是随机行返回数据,因此deos甚至不会检索它不会返回的数据.
在我测试的一张非常大的桌子上
select top 1 percent * from [tablename] order by newid()
Run Code Online (Sandbox Code Playgroud)
花了20多分钟.
select * from [tablename] tablesample(1 percent)
Run Code Online (Sandbox Code Playgroud)
花了2分钟.
对于较小的样品,性能也会提高,TABLESAMPLE
而不会有newid()
.
请记住,这并不像newid()
方法那样随意,但会给你一个不错的样本.
请参阅MSDN页面.
Rob*_*oek 37
newid()/ order by会工作,但对于大型结果集来说会非常昂贵,因为它必须为每一行生成一个id,然后对它们进行排序.
从性能的角度来看,TABLESAMPLE()很好,但是你会得到结果的结果(页面上的所有行都会被返回).
对于性能更好的真随机样本,最好的方法是随机过滤掉行.我在SQL Server联机丛书文章中使用TABLESAMPLE限制结果集中找到以下代码示例:
如果您确实需要单个行的随机样本,请修改查询以随机过滤行,而不是使用TABLESAMPLE.例如,以下查询使用NEWID函数返回Sales.SalesOrderDetail表的大约百分之一的行:
Run Code Online (Sandbox Code Playgroud)SELECT * FROM Sales.SalesOrderDetail WHERE 0.01 >= CAST(CHECKSUM(NEWID(),SalesOrderID) & 0x7fffffff AS float) / CAST (0x7fffffff AS int)
SalesOrderID列包含在CHECKSUM表达式中,以便NEWID()每行计算一次以实现每行的采样.表达式CAST(CHECKSUM(NEWID(),SalesOrderID)和0x7fffffff AS float/CAST(0x7fffffff AS int)计算为0到1之间的随机浮点值.
当针对包含1,000,000行的表运行时,以下是我的结果:
SET STATISTICS TIME ON
SET STATISTICS IO ON
/* newid()
rows returned: 10000
logical reads: 3359
CPU time: 3312 ms
elapsed time = 3359 ms
*/
SELECT TOP 1 PERCENT Number
FROM Numbers
ORDER BY newid()
/* TABLESAMPLE
rows returned: 9269 (varies)
logical reads: 32
CPU time: 0 ms
elapsed time: 5 ms
*/
SELECT Number
FROM Numbers
TABLESAMPLE (1 PERCENT)
/* Filter
rows returned: 9994 (varies)
logical reads: 3359
CPU time: 641 ms
elapsed time: 627 ms
*/
SELECT Number
FROM Numbers
WHERE 0.01 >= CAST(CHECKSUM(NEWID(), Number) & 0x7fffffff AS float)
/ CAST (0x7fffffff AS int)
SET STATISTICS IO OFF
SET STATISTICS TIME OFF
Run Code Online (Sandbox Code Playgroud)
如果您可以使用TABLESAMPLE,它将为您提供最佳性能.否则使用newid()/ filter方法.如果你有一个大的结果集,newid()/ order by应该是最后的手段.
Kyl*_*lan 21
从 MSDN上的大表中随机选择行有一个简单明了的解决方案,可以解决大规模的性能问题.
SELECT * FROM Table1
WHERE (ABS(CAST(
(BINARY_CHECKSUM(*) *
RAND()) as int)) % 100) < 10
Run Code Online (Sandbox Code Playgroud)
RJa*_*nes 11
此链接在Orderby(NEWID())和具有1,7和13百万行的表的其他方法之间进行了有趣的比较.
通常,当在讨论组中询问有关如何选择随机行的问题时,建议使用NEWID查询; 它很简单,适用于小桌子.
SELECT TOP 10 PERCENT *
FROM Table1
ORDER BY NEWID()
Run Code Online (Sandbox Code Playgroud)
但是,当您将NEWID查询用于大型表时,它有一个很大的缺点.ORDER BY子句将表中的所有行复制到tempdb数据库中,并对它们进行排序.这会导致两个问题:
您需要的是一种随机选择不使用tempdb的行的方法,并且随着表变大而不会慢得多.这是一个关于如何做到这一点的新想法:
SELECT * FROM Table1
WHERE (ABS(CAST(
(BINARY_CHECKSUM(*) *
RAND()) as int)) % 100) < 10
Run Code Online (Sandbox Code Playgroud)
这个查询背后的基本思想是我们想要为表中的每一行生成0到99之间的随机数,然后选择随机数小于指定百分比值的所有行.在这个例子中,我们希望随机选择大约10%的行; 因此,我们选择随机数小于10的所有行.
请阅读MSDN中的完整文章.
如果你(不像OP)需要特定数量的记录(这使得CHECKSUM方法难以实现)并且希望比TABLESAMPLE本身提供的更随机的样本,并且还希望比CHECKSUM更快的速度,你可以合并TABLESAMPLE和NEWID()方法,如下所示:
DECLARE @sampleCount int = 50
SET STATISTICS TIME ON
SELECT TOP (@sampleCount) *
FROM [yourtable] TABLESAMPLE(10 PERCENT)
ORDER BY NEWID()
SET STATISTICS TIME OFF
Run Code Online (Sandbox Code Playgroud)
在我的情况下,这是随机性(它不是真的,我知道)和速度之间最直接的妥协.根据需要改变TABLESAMPLE百分比(或行) - 百分比越高,样本越随机,但预计速度会线性下降.(注意TABLESAMPLE不接受变量)
只需按随机数对表格进行排序,然后使用获取前5,000行TOP
.
SELECT TOP 5000 * FROM [Table] ORDER BY newid();
Run Code Online (Sandbox Code Playgroud)
UPDATE
只是试了一下,newid()
电话就足够了 - 不需要所有演员和所有数学.
这是初始种子想法和校验和的组合,在我看来,它可以提供适当的随机结果,而无需使用 NEWID():
SELECT TOP [number]
FROM table_name
ORDER BY RAND(CHECKSUM(*) * RAND())
Run Code Online (Sandbox Code Playgroud)
在 MySQL 中你可以这样做:
SELECT `PRIMARY_KEY`, rand() FROM table ORDER BY rand() LIMIT 5000;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
344771 次 |
最近记录: |