【发布时间】:2013-11-14 21:22:13
【问题描述】:
我有一个大约 800 万行的数据库,我想从中随机选择 n 行。首先我在StackOverflow 和MSDN 上阅读了流行和类似的问题,但是我觉得答案仍然不适合我的需要。
如果我希望在没有额外条件的情况下随机选择一定百分比的行,所提供的解决方案非常有用。但是我想随机选择n行(例如最多5行),都符合一定的条件。
我的数据库包含带有词性、标签、引理和标记等信息的单词。现在我想执行一个查询来选择 5 个与查询中的单词相似的随机词(例如,给我 5 个类似于 fuzzy 的词),这是通过只查看具有相同部分的词来确定的语音和 levenshtein 距离的值高于某个阈值。我在 sql server 中有一个函数可以计算 levenshtein 距离。
上述方法的问题在于,它们要么必须遍历所有记录并计算 levenshtein 距离(这会占用大量时间!),要么只让我选择一个百分比而不是 n 行。
一个运行良好的查询是:
SELECT DISTINCT TOP 5 lower(Words.TOKEN) as LTOKEN, Words.LEMMA, TagSet.POS_Simplified, TagSet.TAG
FROM Words JOIN TagSet on Words.TAG = TagSet.TAG
WHERE NOT Words.LEMMA = 'monarchie' AND TagSet.POS_Simplified = 'noun'
AND TagSet.TAG = 'NOM' AND NOT Words.TOKEN = 'monarchie'
AND [dbo].edit_distance('monarchie', Words.Token) > 0.5
但是,只有 top 我总是得到相同的结果。我需要我的上衣是随机的。使用 NEWID() 之类的方法将首先遍历整个数据库,然后随机选择,这不是我的预期行为,因为它们花费的时间太长。
有没有人想在一个庞大的数据库上快速选择 n 个随机行?
编辑:
某人(不在 StackOverflow 上)可能为我提供了一个带有 OPTION 子句和 fast 关键字的解决方案,该关键字检索它找到的前 n 行。
使用 OPTION(fast 5) 我获得了迄今为止最好的性能(在超过 800 万行的表上需要 10 秒)。我还将 Levenshtein 函数从 SQL 实现更改为 c# 编写的库实现,这大大提高了性能。
Select top 5 * from (
SELECT DISTINCT lower(Words.TOKEN) as LTOKEN, Words.LEMMA, TagSet.POS_Simplified, TagSet.TAG
FROM Words JOIN TagSet on Words.TAG = TagSet.TAG
WHERE NOT Words.LEMMA = 'monarchie' AND TagSet.POS_Simplified = 'noun'
AND TagSet.TAG = 'NOM' AND NOT Words.TOKEN = 'monarchie'
AND [dbo].clrEditDistance('monarchie', Words.Token) > 0.5
) AS T
ORDER BY NEWID()
OPTION(fast 5)
【问题讨论】:
-
添加到您的查询末尾:ORDER BY NEWID() 排序操作在查询执行中最后。或者试试这个查询:SELECT * FROM (
) AS T ORDER BY NEWID() -
除了您问题的随机性方面,使用 SQLServer 的内置全文功能(CONTAINS 等)不是更好吗?
-
@realnumber3012 你的第一个建议仍然会检查我的所有记录,大约需要 5 分钟才能完成(当我为每条记录而不是少数几个记录运行查询时,这基本上是相同的性能) .您的第二个建议只会随机化我查询中的 5 个结果行,这不是我想要的。我想要表中的 5 个随机行,而不是前 5 行的随机顺序。
-
@davek 老实说,我没有意识到 SQLServer 的 CONTAINS 函数的全部功能。我不确定它是否符合我的需求,但我一定会研究一下。
-
TOP N ORDER_BY NEWID() 不只是随机化前 N 个的顺序;它隐式地为每一行分配一个 NEWID,并且由于 NEWID 分布均匀,这将为您提供一个随机(嗯,伪随机)的 N 行集合。从随机性的角度来看,我担心这个“OPTION(fast 5)”;在我看来,允许 SQL Server 选择一个方便的排序来避免 ORDER BY NEWID() 给你的伪随机排序。
标签: sql sql-server performance random query-performance