我在我的服务器和本地机器上运行 MySQL 5.7。我正在使用 Symfony 4.4 和 Doctrine。在我的开发机器上,以下查询(使用从服务器转储的相同数据库)在 ~2 秒内执行,而在服务器上需要 35 秒以上。我认为这与服务器的限制(更少的 RAM 等)有关,但我不能真正在那里投入额外的内存。因此,我正在研究如何改进以下查询 - 最初由 Doctrine 生成。我通过直接在服务器上的 phpMyAdmin 中执行相同的查询来复制同样的缓慢,所以我确定查询是负责任的。我有点卡在这里,希望有任何帮助或正确方向的指示:我需要尝试拆分查询吗?我是否应该尝试添加索引(除了 PK 和 FK,where 子句中引用的列没有索引)?谢谢大家的帮助!
SELECT DISTINCT id_0 FROM (
SELECT DISTINCT id_0, pivot_price_5 FROM (
SELECT b0_.id AS id_0, b0_.price_drop AS price_drop_1, o1_.id AS id_2, o1_.price AS price_3, o1_.currency AS currency_4, o1_.pivot_price AS pivot_price_5, o1_.price_drop AS price_drop_6, o1_.date AS date_7, p2_.id AS id_8, p2_.name AS name_9, p2_.description AS description_10, p2_.normal_price AS normal_price_11, p2_.link AS link_12, p2_.image_link AS image_link_13, p2_.image_thumb_link AS image_thumb_link_14, p2_.merchant_product_id AS merchant_product_id_15, p2_.slug AS slug_16, p2_.created_at AS created_at_17, p2_.updated_at AS updated_at_18, p3_.id AS id_19, p3_.ean AS ean_20, p3_.last_game_check_date AS last_game_check_date_21, p3_.created_at AS created_at_22, p3_.updated_at AS updated_at_23, g4_.id AS id_24, g4_.game_system_key AS game_system_key_25, g4_.created_at AS created_at_26, g4_.updated_at AS updated_at_27
FROM best_offer b0_
INNER JOIN offer o1_ ON b0_.offer_id = o1_.id
INNER JOIN product_version p2_ ON o1_.product_version_id = p2_.id
INNER JOIN product p3_ ON b0_.product_id = p3_.id
INNER JOIN product_game_system p5_ ON p3_.id = p5_.product_id
INNER JOIN game_system g4_ ON g4_.id = p5_.game_system_id
WHERE (o1_.date >= '2020-07-29 00:00:00' AND o1_.date <= '2020-07-29 23:59:59')
AND o1_.pivot_price >= '0'
AND o1_.pivot_price <= '2208'
AND g4_.game_system_key IN ('NSW', 'PS4', 'ONE')
) dctrn_result_inner
ORDER BY pivot_price_5 ASC
) dctrn_result LIMIT 8 OFFSET 40
为了完整起见,PHP代码是:
// In Repository
$qb = $this->createQueryBuilder('best_offer')
->join('best_offer.offer', 'offer')
->addSelect('offer')
->join('offer.productVersion', 'productVersion')
->addSelect('productVersion')
->join('best_offer.product', 'product')
->addSelect('product')
->join('product.gameSystems', 'gameSystems')
->addSelect('gameSystems')
;
$qb
->join('product.game', 'game')
->join('game.ratings', 'game_ratings')
->andWhere('game_ratings.type = :gameRatingType')
->setParameter('gameRatingType', GameRating::TYPE_METACRITIC)
->andWhere('game_ratings.rating > :gameRatingValue')
->setParameter('gameRatingValue', $minMetacritic)
;
$qb = $qb->addCriteria(OfferRepository::createCriteriaOnDate($datetime, 'offer'));
$qb->andWhere('offer.pivotPrice >= :minPivotPrice')
->setParameter('minPivotPrice', $minPivotPrice*100)
;
$qb = $qb->addCriteria(OfferRepository::createCriteriaMaxPivotPrice($maxPivotPrice, 'offer'));
$qb = $qb->addCriteria(GameSystemRepository::createCriteriaSystemsIn($gameSystems, 'gameSystems'));
$qb = $qb->setMaxResults($limit);
foreach ($sortBy as $sortKey => $sortValue) {
$qb = $qb->orderBy($sortKey, $sortValue);
}
return $qb;
由 Controller 中的 PagerFanta 调用:
// In Controller
$adapter = new DoctrineORMAdapter($qb);
$pagerFanta = new Pagerfanta($adapter);
$pagerFanta->setMaxPerPage(8);
$pagerFanta->setCurrentPage($page);
解释结果:
+----+-------------+------------+------------+--------+--------------------------------------------------+-----------------------+---------+--------------------------------+------+----------+-----------------------------------------------------------+--+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | |
+----+-------------+------------+------------+--------+--------------------------------------------------+-----------------------+---------+--------------------------------+------+----------+-----------------------------------------------------------+--+
| 1 | PRIMARY | <derived2> | NULL | ALL | NULL | NULL | NULL | NULL | 2268 | 100.00 | Using temporary | |
| 2 | DERIVED | g4_ | NULL | range | PRIMARY,UNIQ_B478BC43A9F4C69F | UNIQ_B478BC43A9F4C69F | 14 | NULL | 3 | 100.00 | Using where; Using index; Using temporary; Using filesort | |
| 2 | DERIVED | p5_ | NULL | ref | PRIMARY,IDX_1857225C4584665A,IDX_1857225C233EEA7 | IDX_1857225C233EEA7 | 4 | vgdeals.g4_.id | 377 | 100.00 | Using index | |
| 2 | DERIVED | p3_ | NULL | eq_ref | PRIMARY | PRIMARY | 4 | vgdeals.p5_.product_id | 1 | 100.00 | Using index | |
| 2 | DERIVED | b0_ | NULL | ref | UNIQ_8B8D09A53C674EE,IDX_8B8D09A4584665A | IDX_8B8D09A4584665A | 4 | vgdeals.p5_.product_id | 40 | 100.00 | NULL | |
| 2 | DERIVED | o1_ | NULL | eq_ref | PRIMARY,IDX_29D6873ED8DB782E | PRIMARY | 4 | vgdeals.b0_.offer_id | 1 | 5.00 | Using where | |
| 2 | DERIVED | p2_ | NULL | eq_ref | PRIMARY | PRIMARY | 4 | vgdeals.o1_.product_version_id | 1 | 100.00 | Using index | |
+----+-------------+------------+------------+--------+--------------------------------------------------+-----------------------+---------+--------------------------------+------+----------+-----------------------------------------------------------+--+
所涉及表的 SHOW CREATE TABLE 如下(抱歉,我找不到在 SO 中正确格式化它的方法):
最好的报价
CREATE TABLE `best_offer` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`product_id` int(11) NOT NULL,
`offer_id` int(11) NOT NULL,
`price_drop` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UNIQ_8B8D09A53C674EE` (`offer_id`),
KEY `IDX_8B8D09A4584665A` (`product_id`),
CONSTRAINT `FK_8B8D09A4584665A` FOREIGN KEY (`product_id`) REFERENCES `product` (`id`),
CONSTRAINT `FK_8B8D09A53C674EE` FOREIGN KEY (`offer_id`) REFERENCES `offer` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=317260 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
提供
CREATE TABLE `offer` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`product_version_id` int(11) NOT NULL,
`price` int(10) unsigned NOT NULL,
`currency` varchar(3) COLLATE utf8mb4_unicode_ci NOT NULL,
`pivot_price` int(11) NOT NULL,
`price_drop` int(11) DEFAULT NULL,
`date` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `IDX_29D6873ED8DB782E` (`product_version_id`),
CONSTRAINT `FK_29D6873ED8DB782E` FOREIGN KEY (`product_version_id`) REFERENCES `product_version` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=497233 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
PRODUCT_VERSION
CREATE TABLE `product_version` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`merchant_id` int(11) NOT NULL,
`product_id` int(11) NOT NULL,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`description` longtext COLLATE utf8mb4_unicode_ci,
`normal_price` int(10) unsigned DEFAULT NULL,
`link` varchar(4000) COLLATE utf8mb4_unicode_ci NOT NULL,
`image_link` varchar(4000) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`image_thumb_link` varchar(4000) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`merchant_product_id` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL,
`slug` varchar(300) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UNIQ_6EC5C873989D9B62` (`slug`),
KEY `IDX_6EC5C8736796D554` (`merchant_id`),
KEY `IDX_6EC5C8734584665A` (`product_id`),
CONSTRAINT `FK_6EC5C8734584665A` FOREIGN KEY (`product_id`) REFERENCES `product` (`id`),
CONSTRAINT `FK_6EC5C8736796D554` FOREIGN KEY (`merchant_id`) REFERENCES `merchant` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10775 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
产品
CREATE TABLE `product` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ean` char(13) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
`game_id` int(11) DEFAULT NULL,
`last_game_check_date` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UNIQ_D34A04AD67B1C660` (`ean`),
KEY `IDX_D34A04ADE48FD905` (`game_id`),
CONSTRAINT `FK_D34A04ADE48FD905` FOREIGN KEY (`game_id`) REFERENCES `game` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6450 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
PRODUCT_GAME_SYSTEM
CREATE TABLE `product_game_system` (
`product_id` int(11) NOT NULL,
`game_system_id` int(11) NOT NULL,
PRIMARY KEY (`product_id`,`game_system_id`),
KEY `IDX_1857225C4584665A` (`product_id`),
KEY `IDX_1857225C233EEA7` (`game_system_id`),
CONSTRAINT `FK_1857225C233EEA7` FOREIGN KEY (`game_system_id`) REFERENCES `game_system` (`id`) ON DELETE CASCADE,
CONSTRAINT `FK_1857225C4584665A` FOREIGN KEY (`product_id`) REFERENCES `product` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
GAME_SYSTEM
CREATE TABLE `game_system` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`game_system_key` varchar(3) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UNIQ_B478BC43A9F4C69F` (`game_system_key`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
最后,这里是SHOW TABLE STATUS
+---------------------+--------+----+---------+--------+------+----------+---+---------+---------+--------+---------------------+---------------------+---------------------+---------------------+--+--------------------+--+--------------------+--+----------+--+--+--+--+
| best_offer | InnoDB | 10 | Dynamic | 307651 | 46 | 14172160 | 0 | 9469952 | 5242880 | 317260 | 2020-07-29 22:16:33 | 2020-07-31 07:59:09 | | NULL | | utf8mb4_unicode_ci | | NULL | | | | | | |
+---------------------+--------+----+---------+--------+------+----------+---+---------+---------+--------+---------------------+---------------------+---------------------+---------------------+--+--------------------+--+--------------------+--+----------+--+--+--+--+
| game_system | InnoDB | 10 | Dynamic | 17 | 963 | 16384 | 0 | 16384 | 0 | 18 | 2020-07-29 22:16:36 | | NULL | | | NULL | | utf8mb4_unicode_ci | | NULL | | | | |
| offer | InnoDB | 10 | Dynamic | 460330 | 60 | 27836416 | 0 | 7880704 | 6291456 | 497233 | 2020-07-29 22:16:44 | 2020-07-31 07:59:09 | | NULL | | utf8mb4_unicode_ci | | NULL | | | | | | |
| product | InnoDB | 10 | Dynamic | 6432 | 63 | 409600 | 0 | 294912 | 0 | 6450 | 2020-07-29 22:16:44 | 2020-07-31 08:00:57 | | NULL | | utf8mb4_unicode_ci | | NULL | | | | | | |
| product_game_system | InnoDB | 10 | Dynamic | 6419 | 33 | 212992 | 0 | 229376 | 0 | | NULL | | 2020-07-29 22:16:44 | 2020-07-31 07:57:15 | | NULL | | utf8mb4_unicode_ci | | NULL | | | | |
| product_version | InnoDB | 10 | Dynamic | 10749 | 2297 | 24690688 | 0 | 1916928 | 7340032 | 10775 | 2020-07-29 22:16:50 | 2020-07-31 07:59:00 | | NULL | | utf8mb4_unicode_ci | | NULL | | | | | | |
+---------------------+--------+----+---------+--------+------+----------+---+---------+---------+--------+---------------------+---------------------+---------------------+---------------------+--+--------------------+--+--------------------+--+----------+--+--+--+--+