优化疯狂的 MySQL 查询

如何解决优化疯狂的 MySQL 查询

我需要优化这个看起来很疯狂的查询(遗留代码):

SELECT
  E.eventId,E.currency,COALESCE(ROUND(UR.ratings,2),0) as ratings,COALESCE(UR.ratingCount,0) as ratingCount,E.shopSpaceAvail,E.floorPlanImage,COALESCE(O.goingCount,0) as goingCount,(COALESCE(O.goingGroup,'')) as goingGroup,E.userId,E.name,E.withoutTicket,E.mainImage,E.mainImageThumb,E.privateEvent,E.location,E.locationLatitude,E.locationLongitude,E.country3Code,E.country,E.city,E.description,E.startDt as startDt_formatted,E.endDt as endDt_formatted,(
    SELECT
      COUNT(*)
    FROM
      eventIntresteds
    WHERE
      eventId = E.eventId
  ) as interestedCount,(
    CASE WHEN "kaka" = "" THEN 0 ELSE (
      SELECT
        COUNT(*)
      FROM
        eventIntresteds as EI3
      WHERE
        EI3.eventId = E.eventId
        AND EI3.userId IN (
          48,1872,2039,67132,1076,1880,3504,3641,4575,3080,67129,67130,67134
        )
    ) END
  ) as mutualInterestedCount,COALESCE(
    (
      SELECT
        MIN(adultPrice)
      FROM
        eventTickets as ET
      WHERE
        ET.deleted = '0'
        AND ET.eventId = E.eventId
        AND ET.eventTicketType = 'Normal'
    ),0
  ) as minPrice,(
    CASE WHEN 'kaka' = '' THEN '2' WHEN (
      (
        SELECT
          COUNT(*)
        FROM
          eventIntresteds EI1
        WHERE
          EI1.eventId = E.eventId
          AND EI1.userId = 2162
      ) > 0
    ) THEN '1' ELSE '0' END
  ) as isInterested,(
    ROUND(
      (
        (
          3959 * acos(
            cos(radians(0)) * cos(radians(E.locationLatitude)) * cos(radians(E.locationLongitude) - radians(0)) + sin(radians(0)) * sin(radians(E.locationLatitude))
          )
        ) * 1.67
      ),4
    )
  ) as distance,(
    CASE WHEN E.privateEvent = '0'
    OR E.userId = 2162 THEN '1' WHEN 'kaka' = '' THEN '0' WHEN (
      (
        SELECT
          COUNT(*)
        FROM
          userNotifications UN
        WHERE
          UN.eventId = E.eventId
          AND UN.userId = 2162
          AND UN.notificationType = 'eventInvite'
      ) = 0
    ) THEN '0' ELSE '1' END
  ) as isprivateEvent,(
    CASE WHEN (
      E.privateEvent = '0'
      or E.userId = 2162
    ) THEN 1 ELSE (
      SELECT
        COUNT(*)
      FROM
        invites AS I
      WHERE
        I.eventId = E.eventId
        AND I.inviteType = 'Event'
        AND I.deleted = '0'
        AND I.userId = 2162
    ) END
  ) as privateHavingCheck,(
    SELECT
      COUNT(Distinct O1.shopId)
    FROM
      orders O1
      JOIN shops S1 ON (S1.shopId = O1.shopId)
    WHERE
      O1.eventId = E.eventId
      AND S1.deleted = '0'
      AND S1.blocked = '0'
      AND O1.orderStatus = 'Success'
      AND O1.paymentStatus = 'Success'
      AND O1.orderType = 'shopBooth'
      AND O1.refundId = ''
  ) as shopCount
FROM
  events AS E
  JOIN users U ON (
    U.userId = E.userId
    AND U.blocked = '0'
  )
  LEFT JOIN (
    SELECT
      COUNT(*) as ratingCount,AVG(ratings) as ratings,eventId
    FROM
      userRatings
    WHERE
      userRatings.blocked = '0'
      AND userRatings.deleted = '0'
    GROUP BY
      eventId
  ) as UR ON (UR.eventId = E.eventId)
  LEFT JOIN (
    SELECT
      COUNT(*) as goingCount,GROUP_CONCAT(userId) as goingGroup,eventId
    FROM
      orders AS O
    WHERE
      O.orderStatus = 'Success'
      AND O.paymentStatus = 'Success'
      AND orderType = 'EventTicket'
    GROUP BY
      eventId
  ) as O ON (O.eventId = E.eventId)
WHERE
  E.blocked = '0'
  AND E.deleted = '0'
  AND E.approved = '1'
  AND E.privateEvent = '0'
  AND E.endDt >= now()
Having
  eventId != 0
  AND isprivateEvent = '1'
  AND distance <= 1000000
ORDER BY
  minPrice DESC,minPrice DESC
LIMIT
  0,10;

我尝试为此创建索引,但似乎没有任何帮助。查询超级慢。麦汁部分似乎是这样的:

eventId FROM orders AS O WHERE O.orderStatus='Success' AND O.paymentStatus='Success' AND orderType='EventTicket' GROUP BY eventId) as O ON (O.eventId=E.eventId)

这根据explain()扫描了10K+行。我在 (orderStatus,paymentStatus,orderType) 上尝试了复合索引,但没有帮助。

有关如何快速优化此查询的任何建议?我知道它应该重构,但没有时间。我也知道这很糟糕,所以我不希望它变得非常快。但在这一点上,任何加速都将不胜感激。

这是 MySQL 5.7。

编辑:

解释如下:

+----+--------------------+-----------------+------------+-------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------+----------+----------------------------------------+-------+----------+-----------------------------------------------------------------------------------+
| id | select_type        | table           | partitions | type        | possible_keys                                                                                                      | key                                              | key_len  | ref                                    | rows  | filtered | Extra                                                                             |
+----+--------------------+-----------------+------------+-------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------+----------+----------------------------------------+-------+----------+-----------------------------------------------------------------------------------+
|  1 | PRIMARY            | E               | NULL       | ref         | userId,combo,events_idx_blocke_delete_approv_privat_enddt                                                          | events_idx_blocke_delete_approv_privat_enddt     | 4        | const,const,const                |   359 |    33.33 | Using index condition; Using where; Using temporary; Using filesort               |
|  1 | PRIMARY            | U               | NULL       | eq_ref      | PRIMARY,blocked,users_idx_blocked_userid                                                                           | PRIMARY                                          | 8        | db.E.userId                    |     1 |    50.00 | Using where                                                                       |
|  1 | PRIMARY            | <derived9>      | NULL       | ref         | <auto_key0>                                                                                                        | <auto_key0>                                      | 8        | db.E.eventId                   |     2 |   100.00 | NULL                                                                              |
|  1 | PRIMARY            | <derived10>     | NULL       | ref         | <auto_key0>                                                                                                        | <auto_key0>                                      | 8        | db.E.eventId                   |    18 |   100.00 | NULL                                                                              |
| 10 | DERIVED            | O               | NULL       | index_merge | paymentStatus,orderStatus,orderType,eventIdAndDate,eventId,complexIdx3,complexIdx4,complexIdx5,sds                 | paymentStatus,orderType              | 22,22,22 | NULL                                   | 10019 |   100.00 | Using intersect(paymentStatus,orderType); Using where; Using filesort |
|  9 | DERIVED            | userRatings     | NULL       | index       | complexIdx1,eventId                                                                                                | eventId                                          | 8        | NULL                                   |    43 |    25.00 | Using where                                                                       |
|  8 | DEPENDENT SUBQUERY | O1              | NULL       | range       | shopId,refundId,sds | complexIdx3                                      | 44       | NULL                                   |    78 |     2.50 | Using index condition; Using where                                                |
|  8 | DEPENDENT SUBQUERY | S1              | NULL       | eq_ref      | PRIMARY,shopId,deleted,shops_idx_deleted_blocked_shopid                                                    | PRIMARY                                          | 8        | db.O1.shopId                   |     1 |    80.93 | Using where                                                                       |
|  7 | DEPENDENT SUBQUERY | I               | NULL       | ref         | userId,invites_idx_invitet_deleted_userid_eventid                                                          | invites_idx_invitet_deleted_userid_eventid       | 39       | const,db.E.eventId |     1 |   100.00 | Using index                                                                       |
|  6 | DEPENDENT SUBQUERY | UN              | NULL       | ref         | userId,evId,notType,usernotifications_idx_userid_notificati_eventid                                          | usernotifications_idx_userid_notificati_eventid  | 38       | const,db.E.eventId       |   368 |   100.00 | Using index                                                                       |
|  5 | DEPENDENT SUBQUERY | EI1             | NULL       | eq_ref      | eventId_2,userId,eventintresteds_idx_userid_eventid                                                        | eventId_2                                        | 16       |db.E.eventId,const             |     1 |   100.00 | Using where; Using index                                                          |
|  4 | DEPENDENT SUBQUERY | ET              | NULL       | ref         | eventId,type,delEvId,eventtickets_idx_deleted_eventti_eventid_adultpr                                      | eventtickets_idx_deleted_eventti_eventid_adultpr | 91       | const,db.E.eventId       |    24 |   100.00 | Using index                                                                       |
|  3 | DEPENDENT SUBQUERY | EI3             | NULL       | ref         | eventId_2,eventintresteds_idx_userid_eventid                                                        | eventId_2                                        | 8        |db.E.eventId                   |   108 |     0.84 | Using where; Using index                                                          |
|  2 | DEPENDENT SUBQUERY | eventIntresteds | NULL       | ref         | eventId_2,eventId                                                                                                  | eventId                                          | 8        |db.E.eventId                   |   107 |   100.00 | Using where; Using index                                                          |
+----+--------------------+-----------------+------------+-------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------+----------+----------------------------------------+-------+----------+-----------------------------------------------------------------------------------+

编辑 2:

如果有人可以建议一个或多个索引来加快速度,那将不胜感激。 此查询是由 ORM(Sequilize)生成的,因此没有简单的方法可以手动更改它。

解决方法

(请为每张桌子提供 SHOW CREATE TABLE。)

总的来说,JOIN ( SELECT ... ) 的效率低于其他技术。

Tentatie 索引:

E:  INDEX(blocked,deleted,approved,privateEvent,endDt)     -- last in this index
orders:  INDEX(paymentStatus,orderStatus,orderType,-- these first
               refundId,eventId,shopId)
invites:  INDEX(userId,inviteType,eventId)
UN:  INDEX(notificationType,userId)
eventIntresteds:  INDEX(eventId,userId)   -- in this order

简化和优化:

                      ( SELECT  COUNT(*)
                            FROM  eventIntresteds EI1
                            WHERE  EI1.eventId = E.eventId
                              AND  EI1.userId = 2162 ) > 0 ) THEN '1' ELSE '0' END 

-->

                     EXISTS ( SELECT 1
                            FROM eventIntresteds EI1
                            WHERE  EI1.eventId = E.eventId
                              AND  EI1.userId = 2162 )

有几个 CASE 子句,一些使用 EXISTS 可能会更好。

,

请注意,我从您的问题中假设没有机会更改查询语法,因为您说它是由 ORM 生成的,并且您只想以索引的形式进行“快速修复”。

选择列表中的所有子查询在注释中都有 Using index,因此它们已经在使用覆盖索引。我怀疑您是否可以做任何事情来进一步优化这些。相关的子查询很难优化,因为它们必须对结果的每一行执行一次,before HAVING 子句中的条件。

events as E 优化良好,如果我能猜到索引 events_idx_blocke_delete_approv_privat_enddt 位于 WHERE 子句中引用的四列上。

users AS U 由 PRIMARY 键访问,因此可能无法使用索引进一步优化它。

派生表UR需要优化。我会添加这个索引:

ALTER TABLE userRatings ADD INDEX (blocked,ratings);

(我将索引名称留给您,因为您知道要使用什么命名约定。)

派生表 O 正在执行三个单独索引的索引交集。通常单个复合索引比依赖索引合并要好。我会添加这个索引:

ALTER TABLE orders ADD INDEX (orderStatus,paymentStatus,userId);

我知道你说过你在前三列上尝试了复合索引,但添加其他两列可以帮助它作为覆盖索引。

不幸的是,ORDER BY 是按相关子查询的结果排序的,因此无法优化掉 Using filesort

这只是一个怪物查询,试图一次做几件事(例如所有相关的子查询)。你做的任何快速修复都不会有太大帮助。您确实需要对其进行重构才能获得重大改进。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res