【问题标题】:Two left joins and one query to MySQL performance problemMySQL 性能问题的两个左连接和一个查询
【发布时间】:2009-10-19 21:11:22
【问题描述】:

我正在为测验和测验结果设计一个项目。所以我有两个表:quizz_result 和 quizz。 quizz 在 ID 上有主键,而 quizz_result 有外键 QUIZZ_ID 用于测验身份。

下面的查询旨在通过相关信息按日期排序公共测验:如果当前用户 (683735) 参加了这个测验并且有一个有效的结果 (>0) 以及到目前为止有多少人填写了这个测验。

所以我用两个左连接做了这个简单的查询:

select     
  a.*,  
  COUNT(countt.QUIZZ_ID) SUMFILL
from 
  quizz a
  left join quizz_result countt
    on countt.QUIZZ_ID = a.ID 
group by 
   a.ID

并在这些列上添加了索引: 测验:

ID, (ID, DATE), PUBLIC, (PUBLIC, DATE)

在 quizz_result 上:

ID, (QUIZZ_ID, USER_ID), QUIZZ_ID, USER_ID, (QUIZZ_ID, QUIZZ_RESULT_ID)

但是当我进行查询时,它仍然需要大约一分钟。我在 QUIZZ_RESULTS 中只有 34k 行,在 QUIZZ 表中只有 120 行。

当我对这个查询做 EXPLAIN 时,我得到这个:

SELECT TYPE: simple, possible keys:  IDX_PUBLIC,DATE, rows: 34  extra: Using where; Using temporary; Using filesort
SELECT TYPE: simple, possible keys: IDX_QUIZZ_USER,IDX_QUIZZ_RES_RES_QUIZ,IDX_USERID,I..., rows: 1, extra: nothing here
SELECT TYPE: simple, possible keys: IDX_QUIZZ_USER,IDX_QUIZ_RES_RES_QUIZZ,ID_RESULT_ID, rows: 752, extra:  Using index

而且我不知道如何优化这个查询。我看到了:

Using where; Using temporary; Using filesort

但我仍然不知道如何更好地做到这一点,或者最后选择的行数可能是高? 752?

如何优化这个查询?

编辑:我已将查询更新为只有一个左连接的查询,因为它具有相同的长执行时间。

EDIT2:我确实删除了所有内容,仅此而已:这个带有一个查询的简单选择需要 1 秒才能执行。如何优化?

【问题讨论】:

  • 尝试运行 OPTIMIZE TABLE quizz, quizz_result;
  • @Greg 感谢您的提示。我做到了,但时间还是一样

标签: sql mysql performance query-optimization


【解决方案1】:

尝试从您的联接中去除其中的一些附加条件。 将它们移到 where 子句有时会有所帮助。另外,考虑将核心连接放入它们自己的子查询中,然后使用 where 子句对其进行限制。

【讨论】:

  • 我试过了,但没有成功,你能不能更描述一下?
  • 自从我的原始答案以来,您的查询已经发生了一些变化,我认为我的答案不再有效。看看你在这两个表上的索引。确保您在加入的所有列上都有索引。尽可能加入每个表中的唯一值(例如主键和外键)。
【解决方案2】:

关于 (USER_ID, QUIZZ_ID, QUIZZ_RESULT_ID) 的索引怎么样,因为它们都是 AND'd 在一起的?

【讨论】:

  • 我认为您是对的,应该有所帮助,但我已将其添加到此表中,但不幸的是时间相同。所以也许这将是下一个优化。在这个查询中仍然有一些大的和不好的地方
  • 只有一个左连接仍然很慢?我没有很多经验,但这似乎不对。是否还有许多其他看起来不应该花费很长时间的查询?您是否更改了任何默认的数据库引擎参数(线程、共享内存等)?我想在这些之前,请检查您是否确实在 quizz_result 上设置了外键限制。
【解决方案3】:

我已经改成这样了:

select     
  a.*,  
  COUNT(a.ID) SUMFILL
from 
  quizz a
  left join quizz_result countt
    on countt.QUIZZ_ID = a.ID 
group by 
   a.ID

现在很好。

【讨论】:

    【解决方案4】:

    试试这个:

    SELECT  q.*,
            (
            SELECT  COUNT(*)
            FROM    quizz_results qr
            WHERE   qr.quizz_id = q.id
            ) AS total_played,
            (
            SELECT  result
            FROM    qr.quizz_id = q.id
                    AND user_id = 683735
            ) AS current_user_won
    FROM    quizz q
    

    【讨论】:

      猜你喜欢
      • 2020-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-18
      相关资源
      最近更新 更多