我有一个大约 800 万行的数据库,我想从中随机选择 n 行。首先,我已经阅读了StackOverflow上的流行和类似问题以及MSDN上的文章,但是我觉得答案仍然不适合我的需要。
如果我想要在没有额外条件的情况下随机选择一定百分比的行,所提供的解决方案效果很好。但是我想随机选择 n 行(例如最多 5 行),都匹配某个条件。
我的数据库包含带有词性、标签、引理和标记等信息的单词。现在我想执行一个查询来选择 5 个与查询中的词相似的随机词(例如给我 5 个类似于模糊的词),这是通过只查看具有相同词性和值的词来确定的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 实现更改为 ac# 编写的库实现,这大大提高了性能。
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)