如何优化mysql中的巨大左连接?

Posted

技术标签:

【中文标题】如何优化mysql中的巨大左连接?【英文标题】:How to optimize huge left join in mysql? 【发布时间】:2021-03-20 19:45:11 【问题描述】:

我的 mysql 数据库中有两个表:

1) 视频

+----+--------+----------+------+----------+
| id | title  | category | year | director |
+----+--------+----------+------+----------+
|  1 | Title1 | Cat1     | 2021 | A.K.     |
|  2 | Title2 | Cat2     | 2020 | B.C.     |
|  3 | Title3 | Cat3     | 2000 | E.A.     |
+----+--------+----------+------+----------+

2) Videos_insights

+----------+------------+-------+-------+----------+--------+
| video_id |    date    | views | likes | dislikes | shares |
+----------+------------+-------+-------+----------+--------+
|        1 | 2021-03-20 |    13 |     2 |        3 |      1 |
|        1 | 2021-03-19 |    35 |     1 |        3 |      3 |
|        1 | 2021-03-18 |    68 |     5 |        6 |      5 |
|        1 | 2021-03-15 |    86 |     3 |        0 |      1 |
|        2 | 2021-02-13 |   234 |    15 |        1 |     34 |
|        2 | 2021-02-12 |    55 |    15 |        2 |      4 |
|        2 | 2021-02-10 |   331 |   255 |        0 |      0 |
+----------+------------+-------+-------+----------+--------+

我想获取在2021-03-012021-03-31 之间观看的视频。所以结果表应该是这样的:

+--------+-------------------------------------------+
| title  |                date_range                 |
+--------+-------------------------------------------+
| Title1 | ["2021-03-20 - 2021-03-18", "2021-03-15"] |
+--------+-------------------------------------------+

在我的 MySQL 数据库中,我有大约 100 000 个视频,每个视频有大约 100 个 video_insight。

    获得结果表的最佳方法是什么? 如何优化?我的意思是我不想让每个 GET 请求都离开加入?这将花费太长时间,我的服务器会烧毁。

【问题讨论】:

。 .如果你想优化某些东西,你应该显示你正在使用的查询。否则,我只是假设问题是如何获得您指定的结果。 【参考方案1】:

我会单独表示日期:

select v.id, v.title,
       group_concat(date) as dates
from videos v join
     video_insights vi
     on vi.video_id = v.id
where vi.date >= '2021-03-01' and
      vi.date < '2021-04-01'
group by v.id;

请注意,left join 不合适,因为您正在过滤值。

如果您真的想要获取范围,那么您可以使用带有间隙和孤岛方法的窗口函数:

select v.id, v.title, group_concat(date_range)
from videos v join
     (select vi.video_id,
             concat_ws(' - ', min(vi.date), nullif(max(date), min(date))) as date_range
      from (select vi.*,
                   dense_rank() over (partition by vi.video_id order by vi.date) as seqnum
            from video_insights vi
            where vi.date >= '2021-03-01' and
                  vi.date < '2021-04-01'
           ) vi
      group by vi.video_id, date - interval seqnum day
     ) vi
     on vi.video_id = v.id
group by v.id;

【讨论】:

1) 为什么要设置一个不包含在内的日期&lt; '2021-04-01'?制作&lt;= '2021-03-31不是更好吗? 2)你知道第二个问题的答案吗?也许做一些快照? @mickris 。 . .最好使用&lt;。无论“日期”是否具有时间组件,这都有效。这只是一个预防的好习惯。意外错误。

以上是关于如何优化mysql中的巨大左连接?的主要内容,如果未能解决你的问题,请参考以下文章

mysql优化5表左连接

MySql:查询优化(多个左连接)

MySQL:优化格式化日期的左连接

MySQL 索引优化与子查询与左连接

如何使用 MySQL 展平左连接的结果?

mysql中的左连接和右连接有啥区别[重复]