私はランダムに n 行を選択したい約 800 万以上の行のデータベースを持っています。まず、StackOverflowで人気のある同様の質問とMSDNの記事を読みましたが、答えがまだ私のニーズに合わないと感じています。
追加の条件なしでランダムに選択された特定の割合の行が必要な場合、提供されたソリューションはうまく機能します。しかし、特定の条件に一致するn行をランダムに(たとえば、最大5行)選択したいのです。
私のデータベースには、品詞、タグ、補題、トークンなどの情報を含む単語が含まれています。ここで、クエリ内の単語にすべて類似した 5 つのランダムな単語を選択するクエリを実行したいと考えています (たとえば、fuzzyに類似した 5 つの単語を教えてください)。これは、同じ品詞と値を持つ単語のみを調べることによって決定されます。特定のしきい値を超えるレーベンシュタイン距離。レーベンシュタイン距離を計算できる関数がSQLサーバーにあります。
前述の方法の問題は、すべてのレコードを実行してレーベンシュタイン距離を計算する必要があるか (これには多くの時間がかかります!)、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
ただし、トップのみを使用すると、常に同じ結果が得られます。トップをランダムにする必要があります。NEWID() を使用するようなメソッドは、最初にデータベース全体を調べてからランダムに選択しますが、これは時間がかかりすぎるため、私の意図した動作ではありません。
巨大なデータベースで n 個のランダムな行を高速に選択する考えがある人はいますか?
編集:
誰か (StackOverflow ではない) が、 OPTION句とfastキーワードを使用して解決策を提供してくれた可能性があります。これは、見つかった最初の n 行を取得します。
OPTION(fast 5) を使用すると、これまでで最高のパフォーマンスが得られます (800 万行以上のテーブルで 10 秒)。また、レーベンシュタイン関数を 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)