【问题标题】:MYSQL Triple Join Performance help, Copying to Tmp TableMYSQL 三重连接性能帮助,复制到 Tmp 表
【发布时间】:2011-09-17 09:08:16
【问题描述】:

我正在查询一个新闻网站,它将找到 FeaturedContent 以显示在主页上。以这种方式标记的内容被标记为“精选内容”,并按“主页”在精选表格中排序。我目前有所需的输出,但查询运行时间超过 3 秒,我需要减少它。如何优化如下查询?

编辑:按照建议每分钟实现一次视图,低至 0.4 秒:

SELECT f.position, s.item_id, s.item_type, s.title, s.caption, s.date
FROM live.search_all s 
INNER JOIN live.tags t 
ON s.item_id = t.item_id AND s.item_type = t.item_type AND t.tag = 'FeaturedContent' 
LEFT OUTER JOIN live.featured f 
ON s.item_id = f.item_id AND s.item_type = f.item_type AND f.feature_type = 'homepage'
ORDER BY position IS NULL, position ASC, date

这会按顺序返回所有主页功能,然后是按日期排序的其他特色内容。
解释如下:

|-id---|-select_type-|-table-|-type---|-possible_keys---------|-key--------|-key_len-|-ref---------------------------------------|-rows--|-Extra-------------------------------------------------------------|
|-1----|-SIMPLE------|-t2----|-ref----|-PRIMARY,tag_index-----|-tag_index--|-303-----|-const-------------------------------------|-2-----|-Using where; Using index; Using temporary; Using filesort;--------|
|-1----|-SIMPLE------|-t-----|-ref----|-PRIMARY---------------|-PRIMARY----|-4-------|-newswires.t2.id---------------------------|-1974--|-Using index-------------------------------------------------------|
|-1----|-SIMPLE------|-s-----|-eq_ref-|-PRIMARY, search_index-|-PRIMARY----|-124-----|-newswires.t.item_id,newswires.t.item_type-|-1-----|-------------------------------------------------------------------|
|-1----|-SIMPLE------|-f-----|-index--|-NULL------------------|-PRIMARY----|-190-----|-NULL--------------------------------------|-13----|-Using index-------------------------------------------------------|

配置文件如下:

|-Status---------------|-Time-----|
|-starting-------------|-0.000091-|
|-Opening tables-------|-0.000756-|
|-System lock----------|-0.000005-|
|-Table lock-----------|-0.000008-|
|-init-----------------|-0.000004-|
|-checking permissions-|-0.000001-|
|-checking permissions-|-0.000001-|
|-checking permissions-|-0.000043-|
|-optimizing-----------|-0.000019-|
|-statistics-----------|-0.000127-|
|-preparing------------|-0.000023-|
|-Creating tmp table---|-0.001802-|
|-executing------------|-0.000001-|
|-Copying to tmp table-|-0.311445-|
|-Sorting result-------|-0.014819-|
|-Sending data---------|-0.000227-|
|-end------------------|-0.000002-|
|-removing tmp table---|-0.002010-|
|-end------------------|-0.000005-|
|-query end------------|-0.000001-|
|-freeing items--------|-0.000296-|
|-logging slow query---|-0.000001-|
|-cleaning up----------|-0.000007-|

我刚开始阅读 EXPLAIN 输出,所以我不确定我是否有更好的订购方式,或者可以做任何简单的事情来加快这些速度。

search_all 表是定期更新的物化视图表,而标签和特征表是视图。这些视图不是可选的,无法解决。

标签视图结合标签和关系表,根据item_type和item_id返回标签列表,但其他视图都是一个表的简单视图。

编辑:对于物化视图,最大的瓶颈似乎是“复制到临时表”步骤。如果不对输出进行排序,则需要 0.0025 秒(好多了!),但最终输出确实需要排序。有什么方法可以提高该步骤的性能,或解决它吗?

抱歉,如果格式难以阅读,我是新手,不确定它是如何定期完成的。
谢谢你的帮助!如果还需要什么,请告诉我!

编辑:表格大小,供参考:
标签关系:197,411
标签:16,897
故事:51,801
图片:28,383
视频:2,408
精选:13

【问题讨论】:

    标签: mysql performance join copying tmp


    【解决方案1】:

    我认为单独优化您的查询不会很有用。首先的想法是,加入一个由 UNION 组成的子查询本身就是性能的双重瓶颈。

    如果您可以选择更改数据库结构,那么我建议将 3 个表 storiesimagesvideos 合并为一个,如果它们看起来非常相似(添加他们是type ENUM('story', 'image', 'video')) 来区分记录;这将删除子查询和联合。

    此外,您对 storiesvideos 的看法似乎没有使用索引字段来过滤内容。您正在查询索引列吗?

    在不了解完整表结构和数据重新分区的情况下,这是一个非常棘手的问题!

    另一个不涉及对现有数据库进行修改(特别是如果它已经在生产中)的选项是将这些信息“缓存”到另一个表中,该表将由 cron 作业定期刷新。

    缓存可以在不同级别完成,可以在完整查询上进行,也可以在查询的子部分上进行(独立视图,或者 3 个联合体合并到一个缓存表中,等等)

    此选项的可行性取决于是否可以接受显示稍微过时的数据。它可能仅适用于数据的某些部分,这可能意味着您将只缓存查询中涉及的表/视图的子集。

    【讨论】:

    • 感谢您的建议,现在速度快多了。我定期将联合缓存到另一个表中,它下降到 0.4 秒。但是,当我订购结果时,它似乎成为“复制到 tmp 表”的瓶颈。有什么办法可以改善吗?
    猜你喜欢
    • 1970-01-01
    • 2016-09-14
    • 2012-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-15
    • 1970-01-01
    • 2011-03-23
    相关资源
    最近更新 更多