1

次のクエリは、実行に 1.1 秒かかります。これは、インデックスEXPLAINの使用を示しています。FULLTEXT

SELECT SQL_NO_CACHE COUNT(*)
FROM e_entity
WHERE meta_oid=336799 AND MATCH(sIndex07) AGAINST ("#UPR-1393#" IN NATURAL LANGUAGE MODE)

EXPLAIN:
id: 1
select_type: SIMPLE
table: e_entity
type: fulltext
possible_keys: App_Parent,sindex07
key: sIndex07
key_len: 0
ref: (NULL)
rows: 1
extra: Using Where

FULLTEXT列に索引がありsIndex07ます。ただし、このFULLTEXTインデックスが削除され、通常のインデックスに置き換えられるとKEY、クエリは次のようになります。

SELECT SQL_NO_CACHE COUNT(*)
FROM e_entity
WHERE meta_oid=336799 AND sIndex07 LIKE "%#UPR-1393#%"

EXPLAIN:
id: 1
select_type: SIMPLE
table: e_entity
type: ref
possible_keys: App_Parent
key: App_Parent
key_len: 4
ref: const
rows: 331283
extra: Using Where

CREATE TABLE `e_entity` (
`OID` int(11) NOT NULL AUTO_INCREMENT,
`E_E_OID` int(11) DEFAULT NULL,
`UNIQUE_IDX` int(11) NOT NULL,
`APP_OID` int(11) NOT NULL,
`META_OID` int(11) NOT NULL,
`STORE_DATE` datetime NOT NULL,
`REL_DISPLAY` varchar(1024) NOT NULL,
`sIndex01` varchar(1024) NOT NULL,
`SINDEX02` varchar(1024) NOT NULL,
`SINDEX03` varchar(1024) NOT NULL,
`SINDEX04` varchar(1024) NOT NULL,
`SINDEX05` varchar(1024) NOT NULL,
`SINDEX06` varchar(1024) NOT NULL,
`sIndex07` varchar(1024) NOT NULL,
`SINDEX08` varchar(1024) NOT NULL,
`SINDEX09` varchar(1024) NOT NULL,
`sIndex10` varchar(1022) NOT NULL,
`SINDEX11` varchar(1024) NOT NULL,
`SINDEX12` varchar(1024) NOT NULL,
`SINDEX13` varchar(1024) NOT NULL,
`SINDEX14` varchar(1024) NOT NULL,
`sIndex15` varchar(1022) NOT NULL,
`SINDEX16` varchar(1024) NOT NULL,
`SINDEX17` varchar(1024) NOT NULL,
`SINDEX18` varchar(1024) NOT NULL,
`SINDEX19` varchar(1024) NOT NULL,
`SINDEX20` varchar(1024) NOT NULL,
`NINDEX01` double NOT NULL,
`NINDEX02` double NOT NULL,
`NINDEX03` double NOT NULL,
`NINDEX04` double NOT NULL,
`NINDEX05` double NOT NULL,
`NINDEX06` double NOT NULL,
`NINDEX07` double NOT NULL,
`NINDEX08` double NOT NULL,
`NINDEX09` double NOT NULL,
`NINDEX10` double NOT NULL,
`DINDEX01` datetime NOT NULL,
`DINDEX02` datetime NOT NULL,
`DINDEX03` datetime NOT NULL,
`DINDEX04` datetime NOT NULL,
`DINDEX05` datetime NOT NULL,
`DINDEX06` datetime NOT NULL,
`DINDEX07` datetime NOT NULL,
`DINDEX08` datetime NOT NULL,
`DINDEX09` datetime NOT NULL,
`DINDEX10` datetime NOT NULL,
`FREETEXT` mediumtext NOT NULL,
`UID` int(11) DEFAULT NULL,
PRIMARY KEY (`OID`),
KEY `E_E_OID` (`E_E_OID`),
KEY `sIndex01` (`SINDEX01`),
KEY `sIndex02` (`SINDEX02`),
KEY `sIndex03` (`SINDEX03`),
KEY `sIndex04` (`SINDEX04`),
KEY `sIndex05` (`SINDEX05`),
KEY `sIndex06` (`SINDEX06`),
FULLTEXT `sIndex07` (`SINDEX07`),
KEY `sIndex08` (`SINDEX08`),
KEY `sIndex09` (`SINDEX09`),
KEY `sIndex10` (`SINDEX10`),
KEY `sIndex11` (`SINDEX11`),
KEY `sIndex12` (`SINDEX12`),
KEY `sIndex13` (`SINDEX13`),
KEY `sIndex14` (`SINDEX14`),
KEY `sIndex15` (`SINDEX15`),
KEY `sIndex16` (`SINDEX16`),
KEY `sIndex17` (`SINDEX17`),
KEY `sIndex18` (`SINDEX18`),
KEY `sIndex19` (`SINDEX19`),
KEY `sIndex20` (`SINDEX20`),
KEY `dIndex01` (`DINDEX01`),
KEY `dIndex02` (`DINDEX02`),
KEY `dIndex03` (`DINDEX03`),
KEY `dIndex04` (`DINDEX04`),
KEY `dIndex05` (`DINDEX05`),
KEY `dIndex06` (`DINDEX06`),
KEY `dIndex07` (`DINDEX07`),
KEY `dIndex08` (`DINDEX08`),
KEY `dIndex09` (`DINDEX09`),
KEY `dIndex10` (`DINDEX10`),
KEY `nIndex01` (`NINDEX01`),
KEY `nIndex02` (`NINDEX02`),
KEY `nIndex03` (`NINDEX03`),
KEY `nIndex04` (`NINDEX04`),
KEY `nIndex05` (`NINDEX05`),
KEY `nIndex06` (`NINDEX06`),
KEY `nIndex07` (`NINDEX07`),
KEY `nIndex08` (`NINDEX08`),
KEY `nIndex09` (`NINDEX09`),
KEY `nIndex10` (`NINDEX10`),
KEY `rel_display` (`REL_DISPLAY`),
KEY `App_Parent` (`META_OID`),
) ENGINE=InnoDB AUTO_INCREMENT=1245843 DEFAULT CHARSET=utf8    ROW_FORMAT=COMPRESSED

わずか 0.6 秒で完了します。句をネストする必要があることを他の質問で見ましたが、ステートメントMATCHでネストする方法がわかりません。また、句をCOUNT削除すると、インデックスを使用して実行されたクエリは、2 番目のクエリよりも 50% 高速に実行されるため、利点があるように見えますが、残りのクエリと組み合わせて使用​​すると苦労しています。もインデックス化されており、データベースのサイズは 4.5Gb です。meta_oidFULLTEXTFULLTEXTmeta_oidsIndex07varchar(1024)

編集:検索が遅くなった 理由は、検索語にハイフンが含まれているためで、私の特定のケースでは演算子FULLTEXTよりもはるかに大きなデータセットを返します。LIKEハイフンなしの検索はFULLTEXTLIKE

24時間以内に、mysqlバイナリを再コンパイルせずにハイフンで検索できる人に報奨金を授与しますFULLTEXT。これにより、質問の本来の目的である高速化が実現します。

4

2 に答える 2

1

MySQL はクエリ プランナーを使用して、クエリを解決する最善の方法を決定します。通常、「WHERE」コンポーネントを解決するために使用されるインデックスは 1 つだけで、これは適用可能なインデックスのリストから選択されます。可能なインデックスのリストは EXPLAIN の下に表示されpossible_keys、選択されたインデックスは で識別されkeyます。選択を行うために、MySQL はインデックスの一意性などの多くの要因を調べて、どのインデックスが可能な結果のリストを最適に絞り込むかを決定しようとします。

インデックス内で一致する行のリストを絞り込んだら。これらの行をUse Where読み取り、WHERE 句の残りの条件と照合します。

この操作には多くの特殊なケースがあり、MySQL が不適切な選択をすることがあります。クエリ プランナーは MySQL 5.1 で大幅に変更され、再び適切になるまでに数回のリリースが必要でした。

調査するデータがなければ、MySQL が間違った選択をする理由を示唆することは困難です。やっていますが:

SELECT SQL_NO_CACHE COUNT(*)
FROM e_entity
WHERE MATCH(sIndex07) AGAINST ("#UPR-1393#" IN NATURAL LANGUAGE MODE);

フルテキスト インデックスを使用して、MySQL がデータベースから読み取っている行数がわかります。元のクエリでは、これらすべての行を 'meta_oid=336799' に対して解析して、最終的な数を決定する必要があります。

SELECT SQL_NO_CACHE COUNT(*)
FROM e_entity
WHERE meta_oid=336799

App_Parentのインデックスを使用して、MySQL が読み取っている実際の行数がわかりますMETA_OID。2番目のクエリでは、それらの行を解析する必要がありますLIKE "%#UPR-1393#%"

App_Parent後者のクエリが最初のクエリよりもはるかに低い数値を生成する場合、フルテキスト インデックスの代わりに高速である理由を説明できます。

于 2016-11-29T06:26:43.623 に答える