2016-12-31 12 views
1

2つの大きなテーブルがあり、次のクエリを実行する必要があります。テーブルauthors_1(〜20M行)とauthors_2(〜120M行)の両方の構造は同じです。私は私の研究を行い、次のクエリとテーブル構造を考え出しました。クエリにはまだ長い時間(通常10〜20秒)がかかります。ここ2つのユニオン(UNION ALL)巨大テーブルのSELECTパフォーマンスを向上させる

クエリである:

SELECT `fname`, `lname` 
FROM (
    SELECT `fname`, `lname` 
    FROM `authors_1` 
    WHERE 1 AND `lname` LIKE 'AR%' 
    UNION ALL 
    SELECT `fname`, `lname` 
    FROM `authors_2` 
    WHERE 1 AND `lname` LIKE 'AR%') `a` 
GROUP BY CONCAT(`fname`, `lname`) 
ORDER BY `lname` 
LIMIT 0, 999; 

これは、両方のテーブルの同様の構造、(FTインデックスは他のクエリのためのものである)です。

CREATE TABLE `scipers_authors` (
`a_id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
`linker` varchar(255) COLLATE utf8_persian_ci NOT NULL, 
`fname` tinytext COLLATE utf8_persian_ci NOT NULL, /*Should this be tinytext because of FT index or I can use VARCHAR(255) while having FT index?*/ 
`lname` tinytext COLLATE utf8_persian_ci NOT NULL, /*Same for this one*/ 
PRIMARY KEY (`a_id`), 
UNIQUE KEY `linker` (`linker`) USING BTREE, 
KEY `lname_4` (`lname`(4)) USING BTREE, 
KEY `name` (`lname`(128),`fname`(128)) USING BTREE, 
FULLTEXT KEY `fname` (`fname`), 
FULLTEXT KEY `lname` (`lname`), 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_persian_ci; 

これは、(私はlike othersそれを美しくする方法がわからない、私はPMAを使用しています)の上に示された例クエリのEXPLAIN出力されます:

1 PRIMARY <derived2> ALL     476968 Using temporary; Using filesort 
2 DERIVED authors_1 range lname_4,name,lname name 386  184800 Using where 
3 UNION authors_2 range lname_4,name,lname name 386  292168 Using where 
    UNION RESULT <union2,3> ALL      Using temporary 

これを改善するための任意の提案クエリ/構造?

+0

'lname_4'インデックスは、' name'インデックスの接頭辞であるため、必要ないと思います。代わりに 'name'インデックスが使用されることに注意してください。 'LIKE'基準を満たす行は何行ですか? – Barmar

+1

** ** GROUP BY CONCAT( 'fname'、' lname')** ** GROUP BY 'fname'、' lname' ** ** mysqlはインデックスがあればそれを使うことができます –

+0

+1は '私は研究をしてきました....「SOを求める前に研究*を行うことは、常に良いサインです.-)」。また、 'EXPLAIN'も表示します。 – Martin

答えて

2

GROUP BY CONCAT(fname, lname)GROUP BY fname, lnameに変更してみてください。これらの連結をすべて行うことは余分な作業であり、不要です。

これらの意味の違いは、姓と名が異なる2人の人がいる場合ですが、連結された場合は同じです。フレッド・スミスとフレッド・アズミス。そのような組み合わせはおそらくありそうもなく、私はあなたが最初に単一の結果に結合されることを本当に望んでいるのか疑問です。

そして、あなたはあなたが選択している列の同じセットでグループ化している場合、あなたは単にあなたが重複を削除することにしたいので、あなたが代わりに、UNION DISTINCT代わりのUNION ALLを使用することができ

SELECT DISTINCT fname, lname 

を使用することができます。次に、グループ化する必要はありません。つまり、外部クエリでDISTINCTを実行する必要はありません。

+0

+1には「UNION DISTINCT」の使用を推奨します。これを行うと、 'GROUP BY'または' SELECT DISTINCT'を行う必要はないことが明確になるはずです。 –

+0

ありがとうございました、私はそれを "また"から "代わりに"に変更し、さらに説明を加えました。 – Barmar

+0

@Barmar、私はあなたに提案された解決策をテストしました。実行時間が改善されました(PMA表示時間に基づいて53秒から25秒まで)が、まだ時間がかかりました。改善の余地はありますか? – SAVAFA

関連する問題