1

私は次の表を持っています:

CREATE TABLE IF NOT EXISTS `search`
(
    `id` BIGINT(16) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    `string` TEXT NOT NULL,
    `views` BIGINT(16) NOT NULL,
    FULLTEXT(string)
) ENGINE=MyISAM;

合計5,395,939のエントリがあります。用語(「a」など)で検索を実行するには、次のクエリを使用します。

SELECT * FROM `search` WHERE MATCH(string) AGAINST('+a*' IN BOOLEAN MODE) ORDER BY `views` DESC LIMIT 10

しかし、それは本当に遅い=(。上記のクエリの実行には15.4423秒かかりました。明らかに、0.002秒views未満でソートせずに高速です。

ft_min_word_len=1とft_stopword_file=を使用しています

遅くしすぎずに、ビューを全文検索の関連性として使用する方法はありますか?たとえば、検索語「ab」は「bigapple」と一致しますが、「ibgapple」は一致しません(一致する検索プレフィックスが必要です)。

ありがとう

4

1 に答える 1

0

誰も私の質問に答えなかったので、解決策を投稿します (単純なデータベース設計のように適用するのは簡単ではないため、グーグルで検索した場合に期待するものではありませんが、それでも解決策です)この問題に)。MySQL で使用されているエンジンや関数を使用しても、実際には解決できませんでした。すみません=/。

そこで、それを行うための独自のソフトウェアを開発することにしました (C++ で作成しましたが、他のどの言語でも適用できます)。探しているのが小さな文字列 (私の文字列の平均の長さは 15) で単語のプレフィックスを検索する方法である場合は、次のアルゴリズムを使用できます。

1. Create a trie. Each word of each string is put on the trie.
   Each leaf has a list of the ids that match that word.
2. Use a map/dictionary (or an array) to memorize the informations
   for each id (map[id] = information).

文字列の検索: 注: 文字列は「word1 word2 word3...」の形式になります。#、@、$ などの記号が含まれている場合は、" " (スペース) と見なすことができます。例: 「ラファエル・ペレラ」

1. Search for the prefix "Rafael" in the trie. Put all the ids you
   get in a set (a Binary-Search Tree that ignores repeated values).
   Let's call this set "mainSet".
2. Search for the prefix "Perrella" in the trie. For each result,
   put them in a second set (secSet) if and only if they are already
   in the mainSet. Then, clear mainSet and do mainSet = secSet.
3. IF there are still words lefting to search, repeat the second step
   for all those words.

これらの手順の後、すべての結果を含むセットが作成されます。(views, id) のペアを使用してベクトルを作成し、そのベクトルを降順に並べ替えます。だから、あなたが望む結果を得てください...私は30の結果に制限しています。

注: 最初に単語を並べ替えて、同じ接頭辞を持つ単語を削除できます (たとえば、「Jan Ja Jan Ra」では、「Jan Ra」のみが必要です)。アルゴリズムは非常に明白なので、説明しません。

このアルゴリズムは時々悪いことがあります (たとえば、「abcdef ... z」を検索すると、トライ全体が検索されます...)。というわけで、改良を加えました。

1. For each "id" in your map, create also a small trie, that will
   contain the words of the string (include a trie for each m[id]...
   m[id].trie?).

次に、検索を行うには:

1. Choose the longest word in the search string (it's not guaranteed,
   but it is probably the word with the fewest results in the trie...).
2. Apply the step 1 of the old algorithm.
3. Make a vector with the ids in the mainSet.
4. Let's make the final vector. For each id in the vector you've created
   in step 3, search in the trie of this id (m[id].trie?) for all words
   in the search string. If it includes all words, it's a valid id and
   you might include it in the final vector; else, just ignore this id.
5. Repeat step 4 until there are no more ids to verify. After that, just
   sort the final vector for <views, id>.

今では、データを簡単に保存およびロードする方法として、データベースを使用しています。この表のすべてのクエリは、このソフトウェアに直接尋ねられます。レコードを追加または削除するときは、DB とソフトウェアの両方に送信するので、常に両方を最新の状態に保ちます。すべてのデータをロードするのに約 30 秒かかりますが、クエリは高速です (最も遅いもので 0.03 秒、平均で 0.001 秒です。自分のノートブックを使用して、専用のホスティングでは試していません。もっと早く)。

于 2013-01-06T21:11:42.613 に答える