ここでクエリを表示する前に、関連するテーブル定義を示します。
CREATE TABLE phpbb_posts (
topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
poster_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL,
KEY topic_id (topic_id),
KEY poster_id (poster_id),
);
CREATE TABLE phpbb_topics (
topic_id mediumint(8) UNSIGNED NOT NULL auto_increment
);
これが私がやろうとしているクエリです:
SELECT p.topic_id, p.poster_id
FROM phpbb_topics AS t
LEFT JOIN phpbb_posts AS p
ON p.topic_id = t.topic_id
AND p.poster_id <> ...
WHERE p.poster_id IS NULL;
基本的には、対象ユーザー以外の投稿回数がゼロのトピックをすべて検索するクエリです。つまり、対象ユーザーのみが投稿したトピックです。
問題は、クエリに非常に長い時間がかかることです。EXPLAIN は次のとおりです。
Array
(
[id] => 1
[select_type] => SIMPLE
[table] => t
[type] => index
[possible_keys] =>
[key] => topic_approved
[key_len] => 1
[ref] =>
[rows] => 146484
[Extra] => Using index
)
Array
(
[id] => 1
[select_type] => SIMPLE
[table] => p
[type] => ref
[possible_keys] => topic_id,poster_id,tid_post_time
[key] => tid_post_time
[key_len] => 3
[ref] => db_name.t.topic_id
[rows] => 1
[Extra] => Using where; Not exists
)
SQL に関する私の一般的な仮定は、関連するすべての列が主キーまたは外部キー (この場合はそうである) であると仮定すると、any の JOIN は超高速であり、すぐに実行できるということです。
私は他のいくつかのクエリを試しました:
SELECT COUNT(1)
FROM phpbb_topics AS t
JOIN phpbb_posts AS p
ON p.topic_id = t.topic_id;
これは 353340 をすぐに返します。
次に、これらを行います。
SELECT COUNT(1)
FROM phpbb_topics AS t
JOIN phpbb_posts AS p
ON p.topic_id = t.topic_id
AND p.poster_id <> 77198;
SELECT COUNT(1)
FROM phpbb_topics AS t
JOIN phpbb_posts AS p
ON p.topic_id = t.topic_id
WHERE p.poster_id <> 77198;
どちらもかなり時間がかかります (15 ~ 30 秒)。<> を a = に変更すると、まったく時間がかかりません。
私はいくつかの間違った仮定をしていますか? 多分私のDBはただの愚か者ですか?