5

デフォルトでは、Lucene は検索語の先頭にワイルドカードを使用できませんが、次の方法で有効にできます。

QueryParser#setAllowLeadingWildcard(true)

先頭にワイルドカードを使用すると、Lucene がインデックスを使用できなくなることを理解しています。先頭にワイルドカードを使用した検索では、インデックス全体をスキャンする必要があります。

先頭のワイルドカード クエリのパフォーマンスを実証するにはどうすればよいですか? いつから使えsetAllowLeadingWildcard(true)ますか?

次の形式の 1,000 万のドキュメントを含むテスト インデックスを作成しました。

{ name: random_3_word_phrase }

インデックスはディスク上で 360M です。

私のテスト クエリはうまく機能し、実際にパフォーマンスの問題を示すことはできませんでした。たとえば、クエリを実行name:*ingすると、1 秒未満で 110 万を超えるドキュメントが生成されます。クエリを実行name:*ing*すると、同時に 150 万を超えるドキュメントが生成されます。

ここで何が起こっているのですか?なぜこれは遅くないのですか?10,000,000 のドキュメントでは不十分ですか? ドキュメントには複数のフィールドを含める必要がありますか?

4

2 に答える 2

8

メモリの量とメモリ内のトークン インデックスの量によって異なります。

合計 360MB のインデックスは、古いコンピューターですばやく検索できます。360GB のインデックスはもう少し時間がかかります... ;)

例として、古い 2GB のインデックスを起動し、「*e」を検索しました。

8GB のボックスでは、5 秒以内に 500K のヒットが返されました。メモリが 1GB しかないボックスで同じインデックスを試してみたところ、約 20 秒かかりました。

さらに詳しく説明するために、基本的に 1000 万個のランダムな 3 単語フレーズの "** E*" タイプの検索を行う一般的な C# コードを次に示します。

static string substring = "E";

private static Random random = new Random((int)DateTime.Now.Ticks);//thanks to McAden

private static string RandomString(int size)
{
    StringBuilder builder = new StringBuilder();
    char ch;
    for (int i = 0; i < size; i++)
    {
        ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
        builder.Append(ch);
    }

    return builder.ToString();
}

static void FindSubStringInPhrases()
{
    List<string> index = new List<string>();

    for (int i = 0; i < 10000000; i++)
    {
        index.Add(RandomString(5) + " " + RandomString(5) + " " + RandomString(5));
    }

    var matches = index.FindAll(SubstringPredicate);

}

static bool SubstringPredicate(string item)
{
    if (item.Contains(substring))
        return true;
    else
        return false;
}

1,000 万のフェーズがすべてリストに読み込まれた後でも、「var matches = index.FindAll(SubstringPredicate);」に約 1 秒しかかかりません。400 万件以上のヒットを返します。

ポイントは、メモリが高速であるということです。物事がメモリに収まらなくなり、ディスクへのスワップを開始する必要がある場合、パフォーマンスの低下が見られます。

于 2012-08-01T19:51:58.803 に答える
2

私がそれを正しく理解していれば、索引の一部は用語辞書であり、索引付けされたすべての用語のソート済みリストです。ワイルドカードまたは末尾のワイルドカードを使用して検索する場合、Lucene は、多くの用語に共通のプレフィックスがあるという事実を利用できます。一方、先頭のワイルドカードを使用して検索すると、用語辞書全体がスキャンされます。これは最適ではありませんが、用語ディクショナリは、頻度や位置データなど、インデックスの他の部分に比べて小さい傾向があるため、通常、用語ディクショナリの完全なスキャン自体は大きな問題にはなりません。

于 2012-08-01T19:55:21.423 に答える