在两个`OR`条件`mySQL`查询中提高性能

时间:2017-02-13 15:56:01

标签: mysql performance

我将MySQLInnoDB引擎一起使用。

我有两张桌子:

CREATE TABLE `video` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `title` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE = InnoDB;

CREATE TABLE `tags` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `videoId` INT(11) NOT NULL,
  `title` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`id`),
  INDEX `fk_video_tags_idx` (`videoId` ASC),
  CONSTRAINT `fk_video_tags`
    FOREIGN KEY (`videoId`)
    REFERENCES `video` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION
) ENGINE = InnoDB;

video表有~500,000和tags ~400,000条记录。

我写一个简单的查询是这样的:

SELECT *
FROM `video`
LEFT JOIN `tags` ON (video.id = tags.videoId)
WHERE video.id='1' OR tags.id='1'

对我来说,使用OR操作时使用两个条件非常重要。

id中的WHERE字段仅用于示例查询,我不确定结果记录的数量,因此我不能也不想使用LIMIT。< / p>

此查询执行时间约为3秒。这很糟糕,但是当情况更糟时,tags表有大约5,000,000条记录!在这种情况下,执行时间约为160秒!那太糟糕了。

那么,什么是改善执行时间和提高性能的解决方案?

2 个答案:

答案 0 :(得分:2)

我有时想将OR分成不同的SELECTUNION结果。

默认情况下,UNION在结合结果集时具有隐式DISTINCT

如果这不足以让你的速度降低,那么你可以单独运行每一半,看看绝对最短时间是多少。 (对于每一半数据)

SELECT *
FROM `video`
LEFT JOIN `tags` ON (video.id = tags.videoId)
WHERE video.id='1'

UNION

SELECT *
FROM `video`
LEFT JOIN `tags` ON (video.id = tags.videoId)
WHERE tags.id='1'

答案 1 :(得分:1)

尝试选择可能有用的标签并将它们存储在mytags临时表中并加入此标签而不是巨大的标签表:

 SELECT *
 FROM `video`
 JOIN 
 ( SELECT * FROM tags WHERE id=1 or videoid=1) as mytags -- (*)
 ON (video.id = mytags.videoId)

(*)注意: 如果在video.id = tags.videoId条件上加入表格并设置WHERE条件video.id='1' OR tags.id='1',则表示选择符合(video.id = 1 = tags.videoIdOR tags.id=1条件的标记。所以我先建议SELECT,然后加入新的缩小标签表。