在较小的MySQL服务器上查询速度慢

时间:2020-07-30 18:17:33

标签: mysql performance symfony doctrine pagerfanta

我在服务器和本地计算机上都运行MySQL 5.7。我正在使用Symfony 4.4和Doctrine。 在我的开发机上,以下查询(具有从服务器转储的相同数据库)将在〜2s内执行,而在服务器上需要35s +。 我认为这与服务器的限制(较少的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中正确格式化的方法):

BEST_OFFER

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           |  |          |  |  |  |  |
+---------------------+--------+----+---------+--------+------+----------+---+---------+---------+--------+---------------------+---------------------+---------------------+---------------------+--+--------------------+--+--------------------+--+----------+--+--+--+--+

1 个答案:

答案 0 :(得分:1)

ORDER BY pivot_price_5 ASC没有用。这是因为子查询是(但定义为)无序集合。 (添加LIMIT使其毫无用处。)但是似乎您应该摆脱内部子查询。

DISTINCTLIMIT –您知道DISTINCT首先发生吗?

主要IN中有两个范围,一个WHERE;他们中只有一个可以使用索引。我建议您进行以下每个操作,以便优化器可以选择更好的。 (注意:对于不同的数据集,优化器可能会选择具有不同性能的其他INDEX。)

INDEX(pivot_price)
INDEX(date)

请提供EXPLAINsCREATE TABLEsSHOW TABLE STATUS。 (我想分析对您的“二维” WHERE使用分区是否值得。)

您似乎正在从许多表中获取几列,只是最终忽略了那些多余的列。清理将有助于提高性能。

相关问题