私のクエリが遅くなる理由を理解できません。それは、チーム、プレーヤー、機器、メタデータの4つのテーブルです。プレーヤーと機器の記録にはFKチームがあり、チームをプレーヤーと機器の親とする。これら3つのテーブルの行にはそれぞれ、作成日、作成者のユーザーIDなどのメタデータが記録されています。2つの左結合を含むこのMySQLクエリを最適化するにはどうすればよいですか?
私が一度に取得したいのは、特定のチーム、作成日順。私はメタデータテーブルから開始し、player_とequipmentテーブルを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の周りに、本当に遅いダウンを参照するには、多数の行を追加する必要があります。私が理解できないのは、「... AND player.team_id = 1」のように、あるテーブルのwhere句にフィルタをかけるだけで本当にすばらしい理由です。しかし、もう一方を追加すると「.. AND(player.team_id = 1 OR equipment.team_id = 1) "それははるかに長い時間がかかります。
ここに表とデータ型があります。多くのことを助けてくれると思われるものの1つは、metadata_idとteam_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のプレイヤーと設備上の2つのSELECTSのUNIONを行うことによって、これをスピードアップする可能性が実現するが、それに注意してください、私はネイティブにUNIONのをサポートしていません使用していますORMとだから私はむしろ、代わりにこのクエリを最適化できるかどうか試してみたいと思います。また、私はただ好奇心が強いです。
ああ、あなたのbaz-bar-foo fooを本当のbazに置き換えることはできますか? – markus
申し訳ありません私はあなたを失ったと思いますが、実際のテーブル名でfoo、bar、bazを置き換えることを意味すると思いますか? – mcsnolte
あなたが見ることができるように、変数名fooとbazを使用するコードのようにするのはかなり難しいので...しかし、あなたのbazをfooしたいなら、私はbarです! – markus