0

テキスト識別子を含む列を持つ大きなテーブル (200 万行) があります (これらは種のラテン名、Homo_sapiens、Tyranosaurus_rex などです)。

種のラテン名と「一般的な」名前を含む別のテーブルがあり、これをクエリして、ラテン名の小さな選択 (〜 140 名) を取得し、その一部を最初のテーブルにマップできます。名前がこの小さな選択に正確にマップされている最初のテーブルの行を取得したいと考えています。共通名には mySQL 'FULLTEXT" インデックスがあるため、小さな選択 (140 行のみ) を取得するために使用しているクエリは高速に実行されます。

select distinct latin_name from common_names_table 
  where match(common_name) against('+*mo*' in boolean mode)

しかし、SQL 演算子を使用してこれらを大規模な 200 万行のテーブルに一致させようとすると、IN何分もかかります。

select latin_name,popularity from big_table 
 where latin_name in (
  select distinct latin_name from common_names_table 
    where match(common_name) against('+*mo*' in boolean mode)
  )
 ORDER BY popularity DESC LIMIT 50;

これは、latin_name 列に全文索引と通常の索引の両方を設定した場合でも当てはまります。

CREATE FULLTEXT INDEX name_fulltext_index ON big_table (latin_name);
CREATE INDEX name_index          ON big_table (latin_name);

どうすればこれをスピードアップできますか? INインデックス付きテキスト フィールドで演算子を使用する際に問題はありますか? もしそうなら、テキストフィールドに使用できる特別な種類の「完全一致」インデックスはありますか? latin_name フィールドはどちらも "VARCHAR" 型で、最大長は小さなテーブルでは 190、大きなテーブルでは 200 です (違いがある場合)。

助けてくれてありがとう


要求どおり - テーブル定義は次のとおりです。

CREATE TABLE `big_table` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `parent` int(11) NOT NULL,
  `latin_name` varchar(200) DEFAULT NULL,
  `popularity` double DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `pop_index` (`popularity`),
  KEY `name_index` (`latin_name`),
  FULLTEXT KEY `name_fulltext_index` (`latin_name`)
) ENGINE=InnoDB AUTO_INCREMENT=1781766 DEFAULT CHARSET=utf8;

CREATE TABLE `common_name_table` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `latin_name` varchar(190) CHARACTER SET utf8mb4 NOT NULL DEFAULT '',
  `common_name` varchar(190) CHARACTER SET utf8mb4 NOT NULL,
  PRIMARY KEY (`id`),
  KEY `name_index` (`latin_name`),
  FULLTEXT KEY `common_name_index` (`common_name`)
) ENGINE=InnoDB AUTO_INCREMENT=2024 DEFAULT CHARSET=utf8;
4

3 に答える 3

1

「IN」の代わりに結合を試すことができます。

select
b.latin_name,
b.popularity
from
(
    select distinct latin_name from common_names_table 
    where match(common_name) against('+*mo*' in boolean mode)
) a
left join big_table as b on (a.latin_name=b.latin_name)
where b.latin_name IS NOT NULL
ORDER BY b.popularity DESC LIMIT 50;

左結合 (右側が null ではない) は、おそらく内部結合よりも高速です。

于 2016-10-18T09:08:23.257 に答える