我无法弄清楚为什么我的查询变慢了。它归结为四个表:团队、球员、设备和元数据。玩家和设备中的记录对团队有 FK,使团队成为玩家和设备的父级。并且所有这三个表的行在元数据中都有一条记录,其中存储了创建日期、创建者用户 ID 等内容。
我想一次检索的是属于特定团队的任何球员和设备记录,按创建日期顺序排列。我从元数据表开始,通过 metadata_id FK 离开加入球员和设备表,但是当我尝试过滤 SELECT 以仅检索某个团队的记录时,当有很多行时,查询会大大减慢。
这是查询:
SELECT metadata.creation_date, player.id, equipment.id
FROM
metadata
JOIN datatype ON datatype.id = metadata.datatype_id
LEFT JOIN player ON player.metadata_id = metadata.id
LEFT JOIN equipment ON equipment.metadata_id = metadata.id
WHERE
datatype.name IN ('player', 'equipment')
AND (player.team_id = 1 OR equipment.team_id = 1)
ORDER BY metadata.creation_date;
您需要添加很多行才能真正看到减速,每个表大约 10,000 行。我不明白的是,如果我只在一个表上的 where 子句中进行过滤,为什么它真的很快,例如:“... AND player.team_id = 1”但是当我添加另一个以使其成为“.. . AND (player.team_id = 1 OR equipment.team_id = 1)" 这需要很长很长的时间。
这是表和数据类型。请注意,似乎有很大帮助的一件事,但不是全部,是元数据_id 和团队_id 的播放器和设备上的组合键。
CREATE TABLE `metadata` (
`id` INT(4) unsigned NOT NULL auto_increment,
`creation_date` DATETIME NOT NULL,
`datatype_id` INT(4) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
CREATE TABLE `datatype` (
`id` INT(4) unsigned NOT NULL auto_increment,
`name` VARCHAR(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
CREATE TABLE `team` (
`id` INT(4) unsigned NOT NULL auto_increment,
`metadata_id` INT(4) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
CREATE TABLE `player` (
`id` INT(4) unsigned NOT NULL auto_increment,
`metadata_id` INT(4) unsigned NOT NULL,
`team_id` INT(4) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
CREATE TABLE `equipment` (
`id` INT(4) unsigned NOT NULL auto_increment,
`metadata_id` INT(4) unsigned NOT NULL,
`team_id` INT(4) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
ALTER TABLE `metadata` ADD INDEX ( `datatype_id` ),
ADD INDEX ( `creation_date` );
ALTER TABLE `team` ADD INDEX ( `metadata_id` );
ALTER TABLE `player` ADD INDEX `metadata_id` ( `metadata_id`, `team_id` ),
ADD INDEX ( `team_id` );
ALTER TABLE `equipment` ADD INDEX `metadata_id` ( `metadata_id`, `team_id` ),
ADD INDEX ( `team_id` );
ALTER TABLE `metadata` ADD CONSTRAINT `metadata_ibfk_1` FOREIGN KEY (`datatype_id`) REFERENCES `datatype` (`id`);
ALTER TABLE `team` ADD CONSTRAINT `team_ibfk_1` FOREIGN KEY (`metadata_id`) REFERENCES `metadata` (`id`);
ALTER TABLE `player` ADD CONSTRAINT `player_ibfk_1` FOREIGN KEY (`metadata_id`) REFERENCES `metadata` (`id`);
ALTER TABLE `player` ADD CONSTRAINT `player_ibfk_2` FOREIGN KEY (`team_id`) REFERENCES `team` (`id`);
ALTER TABLE `equipment` ADD CONSTRAINT `equipment_ibfk_1` FOREIGN KEY (`metadata_id`) REFERENCES `metadata` (`id`);
ALTER TABLE `equipment` ADD CONSTRAINT `equipment_ibfk_2` FOREIGN KEY (`team_id`) REFERENCES `team` (`id`);
INSERT INTO `datatype` VALUES(1,'team'),(2,'player'),(3,'equipment');
请注意,我意识到我可以通过对给定团队 id 的玩家和设备执行两个 SELECTS 的 UNION 来轻松加快这一速度,但是我使用的 ORM 本身并不支持 UNION,所以我更愿意尝试看看如果我可以优化此查询。我也只是很好奇。