2016-12-27 21 views
2

私はこの(私はこれらすべての無関係なフィールドを削除した)のようなテーブルだ:MySQLの全文検索

CREATE TABLE `products` (
    `id` bigint(20) NOT NULL, 
    `keywords` varchar(2000) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    FULLTEXT KEY `KEYWORDS_FTIDX` (`keywords`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

を2列あります

  1. ID:131072、キーワードは:製品1
  2. ID:131073、キーワード:product2

私は、クエリSELECT * FROM products WHERE MATCH(keywords) AGAINST('product1' IN BOOLEAN MODE)を実行する場合、それのWi私は期待通りに最初の行を返します。

私がクエリSELECT * FROM products WHERE MATCH(keywords) AGAINST('product1' IN BOOLEAN MODE) LIMIT 10に制限を加えれば、何も得られません。

LIMIT SELECT * FROM products WHERE MATCH(keywords) AGAINST('product1' IN BOOLEAN MODE) LIMIT 100に大きな数値を使用しようとすると、もう一度動作します。

誰でも私にこの権利を行えるように教えてください。

+0

個人的には追加オプションがあれば、これをデータベース管理者コミュニティに投稿する必要があります。つまり、あなたがあなたのT-SQLステートメントに追加したすべてのエクストラを理解している場合です。あなたが単にそれを戻さなければ、いくつかのことを戻します。 – Edward

+0

私は開発目的のためにすべてのデフォルト設定を持つドッカーコンテナでmysqlを実行します。だから私はそれがオプションについてだとは思わない。しかし、あなたのアドバイスのおかげで、私はデータベース管理者のコミュニティにもっと良い解決策があるかどうかを見てみましょう。 – Sean

答えて

0

私は長い間、全文索引の実装について何かを読んだ。インデックスエンジンの一部については、削除されたレコードをインデックスから削除するのではなく削除済みとしてマークし、削除されたアイテムはインデックス検索操作でヒットし、最終結果から削除してユーザーに返します。

mysqlがこのように動作する場合は、MATCHでLIMITを使用します。mysqlはパフォーマンス向上のためにインデックスの先頭部分を検索します。しかし、これらの行はすべて削除されているので、空の結果が得られます。

は、その後、私はそれら行なったし、結果はそれを証明した:

  1. 、私は質問の部分に掲載まったく同じクエリを使用してテストテーブルを作成します。
  2. 2つの行を挿入します。id:1、keywords:product1、id:2、keywords:product2。
  3. 検索クエリ:SELECT * FROM products WHERE MATCH(keywords) AGAINST('product1' IN BOOLEAN MODE) LIMIT 1を実行すると、正しい結果が得られます。
  4. これら2つのレコードをすべて削除し、再度挿入します。
  5. 手順3のクエリを実行すると、何も得られません。
  6. しかし、私が実行した場合:SELECT * FROM products WHERE MATCH(keywords) AGAINST('product1' IN BOOLEAN MODE) LIMIT 2、それは正しい結果を再び返します。

今のところ、クイックフィックスでは一致条件を別の条件と組み合わせることができます。その場合、mysqlはマッチフェーズで必要以上にフェッチします。そして、このクエリの動作:SELECT * FROM products WHERE MATCH(keywords) AGAINST('product1' IN BOOLEAN MODE) AND id >= 0 LIMIT 1

私はまた、クエリで説明した、それも同様にKEYWORDS_FTIDXインデックスを使用しました。

MySQLのドク(https://dev.mysql.com/doc/refman/5.6/en/innodb-fulltext-index.html)からこれらの行はまた問題について:

補助インデックステーブル内の多数の小さな欠失をもたらす可能性のフルテキストインデックス列を持つレコードを削除し、これらへの同時アクセスを行います競合する点を示します。この問題を回避するには、レコードがインデックステーブルから削除され、インデックス付きレコードがフルテキストインデックスに残っている場合は、削除されたドキュメントのドキュメントID(DOC_ID)が特殊なFTS_ _DELETEDテーブルに記録されます。クエリ結果を返す前に、FTS_ _DELETEDテーブルの情報を使用して、削除されたドキュメントIDをフィルタ処理します。この設計の利点は、削除が迅速かつ安価であることです。欠点は、レコードの削除後にインデックスのサイズがすぐに縮小されないことです。削除されたレコードのフルテキストインデックスエントリを削除するには、インデックス付きテーブルに対して、innodb_optimize_fulltext_only = ONを指定してOPTIMIZE TABLEを実行して、フルテキストインデックスを再構築する必要があります。詳細については、「InnoDBフルテキストインデックスの最適化」を参照してください。