たいのですが最適なこのMySQLのクエリがどのような左加?
-
13-09-2019 - |
質問
できませんね私のクエリが鈍化。何をあげた四つのテーブル:チームのプレイヤー、機器、およびメタデータを指すものとします。記録のプレイヤー、機器、FKをチーム、チームは、親プレーヤー装備。すべてのテーブルの行それぞれ記録メタデータが格納されているようなものは、作成日、作成者のユーザid等
うを検索では、一部の他のプレーヤー装備の記録に所属する特定のチームを創ります。から始めると、メタデータテーブル左の参加プレーヤーの機器テーブルのmetadata_id FKしてしまっているんですけどしフィルターの選択のみ取得するレコードに特定のチームは、クエリを遅く大きな時間がされています。
こちらはにゃ
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句一つのテーブルは、例えば:"...やプレイヤー。team_id=1"の場を追加しますので"...(プレイヤー。team_id=1または装備。team_id=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');
ご注意ください その実現が簡単に速することによってEUの二つの選択プレイヤーは、機器に指定されたチームidが、ORMを使用していないネイティブの支援組合のいろくみを見出すことができれば最適なこのクエリです。もんだの不思議です。
解決
MySQLでの最適化"OR
"条件です。
共通の救済策は分割クエリの二つの単純なクエリで使用 UNION
を結合します。
(SELECT metadata.creation_date, datatype.name, player.id
FROM metadata
JOIN datatype ON datatype.id = metadata.datatype_id
JOIN player ON player.metadata_id = metadata.id
WHERE datatype.name = 'player' AND player.team_id = 1)
UNION ALL
(SELECT metadata.creation_date, datatype.name, equipment.id
FROM metadata
JOIN datatype ON datatype.id = metadata.datatype_id
JOIN equipment ON equipment.metadata_id = metadata.id
WHERE datatype.name = 'equipment' AND equipment.team_id = 1)
ORDER BY creation_date;
使用には括弧内の ORDER BY
対象の結果 UNION
やみくもに、結果の SELECT
.
更新: 何をやっているといいを明会で使用してください。も呼ばれるSQL antipatternはあるものの、ORMの枠組みを利用します。
だってこの場合には関係のチームや選手、チームです。選手にはない設備機器なっない共通のスーパータイプ.この誤解を招くも、OO感との関係感でモデル化していることができてうれしいです。
僕はゴ metadata
や datatype
ます。これらの抗関係の構造物です。代わりに使用しますの team_id
(あるいは外部キーを teams
いことがあります。治療の選手として、機器異なる種類です。フェッチしている場合は別途使用できません UNION
おORM.その結果セットします。
いを取得すべて単一のSQLクエリ。