0

テーブル内のすべての行をスキャンしている理由について、mysqlクエリに頭を悩ませようとしている人

私は2つのテーブルtopic_entryとtopic_userを持っています

CREATE TABLE `topic_entry` (
  `entry_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `topic_id` bigint(20) unsigned NOT NULL,
  `entry_created` datetime NOT NULL,
  `entry_object` text,
  `level` tinyint(4) NOT NULL DEFAULT '3',
  PRIMARY KEY (`entry_id`),
  KEY `entry_created` (`entry_created`),
  KEY `level` (`level`),
  KEY `topic_id_2` (`topic_id`,`entry_id`)
) ENGINE=MyISAM;

CREATE TABLE `topic_user` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `topic_id` bigint(20) unsigned NOT NULL,
  `user_id` varchar(100) NOT NULL,
  `private` enum('y','n') DEFAULT NULL,
  `freq` enum('a','d','w') DEFAULT NULL,
  `topic_id_freq` varchar(10) DEFAULT NULL,
  `casematch` enum('0','1') DEFAULT '0',
  `textmatch` enum('0','1') DEFAULT '0',
  `topic_name_case` varchar(100) DEFAULT '',
  PRIMARY KEY (`id`),
  UNIQUE KEY `topic_id_user_id` (`topic_id`,`user_id`),
  KEY `user_id` (`user_id`),
  KEY `topic_id_freq` (`topic_id_freq`)
) ENGINE=MyISAM;

これは私が実行しようとしているクエリです

explain 
select  te.topic_id,te.entry_id 
from topic_entry te 
WHERE te.topic_id in (select topic_id 
                        from topic_user where user_id ='xyz') 
    AND te.level=4 
    AND te.entry_id > 0 
ORDER BY te.entry_id DESC 
LIMIT 5;

Explain 出力は、すべての行をスキャンしていることを示しています。

|  1 | PRIMARY| te | range  | PRIMARY,level | PRIMARY | 8 | NULL| **722978** | Using where              | 
|  2 | DEPENDENT SUBQUERY | topic_user | unique_subquery | topic_id_user_id,user_id | topic_id_user_id | 310     | func,const |      1 | Using index; Using where |
4

3 に答える 3

3

これを試して:

EXPLAIN
SELECT      te.topic_id,te.entry_id 
FROM        topic_entry te 
JOIN        topic_user tu ON te.topic_id = tu.topic_id AND tu.user_id = 'xyz'
WHERE       te.level=4 
AND         te.entry_id > 0 
ORDER BY    te.entry_id DESC 
LIMIT 5;
于 2012-09-12T16:12:11.000 に答える
0

WHERE 句のキーのシーケンスを変更してみてください:
WHERE te.topic_id in (select topic_id from topic_user where user_id ='xyz') AND te.level=4 AND te.entry_id > 0
100
WHERE te.topic_id in (select topic_id from topic_user where user_id ='xyz') AND te.entry_id > 0 AND te.level=4
% 確信があるわけではありませんが (現時点ではテストできません)、役立つ場合があります。
その理由は、MySQL がキーをマップしようとして失敗し
topic_id, level, entry_idKEY topic_id_2余分なフィールドが原因で失敗するためです。

PS と "Sly Raskal" にはさらに優れた解決策があります。または、両方を組み合わせてみることもできます。

于 2012-09-12T16:12:22.450 に答える
0

どうですか

explain extended
select  te.topic_id,te.entry_id 
from topic_entry te LEFT JOIN topic_user tu ON
    te.topic_id = tu.topic_id AND tu.user_id = 'xyz'
WHERE 1 = 1
    AND te.level=4 
    AND te.entry_id > 0 
ORDER BY te.entry_id DESC 
LIMIT 5;
于 2012-09-12T16:14:07.817 に答える