1

我有一个表朋友

CREATE TABLE IF NOT EXISTS `friends` (
    `fr_id` int(11) NOT NULL AUTO_INCREMENT,
    `fr_sender` int(11) NOT NULL,
    `fr_receiver` int(11) NOT NULL,
    `fr_validate` enum('0','1','2') NOT NULL DEFAULT '0',
    PRIMARY KEY (`fr_id`),
    KEY `fr_sender` (`fr_sender`),
    KEY `fr_receiver` (`fr_receiver`),
    KEY `fr_validate` (`fr_validate`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=2397953 ;

fr_id       => index
fr_sender   => sender of the friend request
fr_receiver => the receiver
fr_falidate => 0 = no reply, 1 = request accepted, 2 = request refused.

我的 mysql-slow.log 有很多行用于此查询:

SELECT fr_id FROM friends WHERE (fr_sender = '113405' OR fr_receiver = '113405') && fr_validate = "1";
# Query_time: 5.607869  Lock_time: 0.000052 Rows_sent: 106  Rows_examined: 833517

我怎样才能优化我的这个查询的索引?

谢谢你。

4

1 回答 1

1

当您在两个不同OR的条件之间使用时,优化起来很棘手。它通常会导致代价高昂的表扫描。

这是一个解决方法:

ALTER TABLE friends 
 ADD INDEX (fr_validate, fr_sender),
 ADD INDEX (fr_validate, fr_receiver);

SELECT fr_id FROM friends WHERE fr_validate = '1' AND fr_sender = '113405'
UNION 
SELECT fr_id FROM friends WHERE fr_validate = '1' AND fr_receiver = '113405'

创建两个索引的原因是每个子查询都有一个相应的索引,以尽可能减少检查的行。然后将每个子查询的结果组合起来,从而提供与原始查询等效的结果集。

PS:请对字符串文字和日期文字使用单引号。MySQL 默认允许双引号起到相同的作用,但是如果您使用另一个 RDBMS 品牌,或者如果您SET SQL_MODE=ANSI_QUOTES在 MySQL 中,您会发现双引号的标准含义是用于分隔表名和列名,而不是字符串。

于 2013-11-11T16:30:13.117 回答