查询在localhost上运行正常但在我们的服务器上运行速度非常慢

时间:2011-03-06 15:37:55

标签: mysql query-optimization

我们在每张桌子上测试了100万条记录,结果很好,总是低于0,08。 所以我们在我们的服务器上实现了,但它在那里非常慢,最多需要36秒。

我们在优化我们在测试机器上运行的查询之前已经请求了帮助,我们详细介绍了我们的一对多关系的基本结构: Problems to optimize large query and tables structure

这是最终查询,我们在获得上述链接的帮助后使用的那个:

explain 
SELECT
    st.sid, st.title, st.summary, st.storynotes, st.thumb, st.completed, st.wordcount, st.rid, st.date, st.updated,
    stats.total_reviews, stats.total_recommendations,
    (SELECT GROUP_CONCAT(CAST(catid AS CHAR)) FROM fanfiction_stories_categories WHERE sid = st.sid) as categories,
    (SELECT GROUP_CONCAT(CAST(genre_id AS CHAR)) FROM fanfiction_stories_genres WHERE sid = st.sid) as genres,
    (SELECT GROUP_CONCAT(CAST(warning_id AS CHAR)) FROM fanfiction_stories_warnings WHERE sid = st.sid) as warnings
    FROM
    fanfiction_stories st
    LEFT JOIN fanfiction_stories_stats stats ON st.sid = stats.sid
    JOIN fanfiction_stories_categories cat ON st.sid = cat.sid AND cat.catid = 924
    WHERE validated = 1
    ORDER BY updated DESC
    LIMIT 0, 15

这就是解释:

http://dl.dropbox.com/u/14508898/Printscreen/stackoverflow_explain_print_003.PNG

影响0行,找到6行。 1次查询的持续时间:31,356秒

更新
我们在fanfiction_stories中删除了以前数据库结构的一些旧索引,并为fanfiction_stories_categories添加了新索引,现在速度要快得多。这是更新的解释:

http://dl.dropbox.com/u/14508898/Printscreen/stackoverflow_explain_print_004.PNG

抱歉,我使用的程序只将解释表格式化为HTML,CSV等,不会在此处显示ASCII表。

我们可以进一步优化它吗?非常感谢任何帮助。

2 个答案:

答案 0 :(得分:0)

您可以使用明确的INNER JOIN代替JOIN,而不是JOIN:

它可能也是您正在做的所有GROUP_CONCAT,它们非常耗费内存。

SELECT
    st.sid, st.title, st.summary, st.storynotes, st.thumb, st.completed, st.wordcount, st.rid, st.date, st.updated,
    stats.total_reviews, stats.total_recommendations,
    (SELECT GROUP_CONCAT(CAST(catid AS CHAR)) FROM fanfiction_stories_categories WHERE sid = st.sid) as categories,
    (SELECT GROUP_CONCAT(CAST(genre_id AS CHAR)) FROM fanfiction_stories_genres WHERE sid = st.sid) as genres,
    (SELECT GROUP_CONCAT(CAST(warning_id AS CHAR)) FROM fanfiction_stories_warnings WHERE sid = st.sid) as warnings
    FROM
    fanfiction_stories st
    LEFT JOIN fanfiction_stories_stats stats ON st.sid = stats.sid
    INNER JOIN fanfiction_stories_categories cat ON st.sid = cat.sid AND cat.catid = 924
    WHERE validated = 1
    ORDER BY updated DESC
    LIMIT 0, 15

答案 1 :(得分:0)

虽然我没有表结构和样本数据来模拟,但这应该可行。通过删除每个(SELECT ...)作为列并只留下左连接,通过sid对整个外部查询进行分组应该给出相同的结果。我认为它比每个子查询AS列比普通查询/连接更有效。无论如何,Group_Concat都根据末尾的“sid”进行分组,并且应该保留......唯一可能是问题的是这些concat字段末尾的任何NULL值,然后可以用IFNULL()测试进行换行。

我会确保这些表中的每一个都有用于连接的“sid”的索引。此外,您的主要故事表的条件为Validated for criteria = 1。

根据您的反馈,我会按照类别将标准和第一个表格移到顶部。首先获取一个类别,然后查看与之关联的故事。然后,仅从那些故事中,连接其余的类型,警告,评论等。你显然有一组较小的类别,所以我会把它作为查询中的主表。让我知道这是如何工作的。

SELECT STRAIGHT_JOIN
      st.sid, 
      st.title, 
      st.summary, 
      st.storynotes, 
      st.thumb, 
      st.completed, 
      st.wordcount, 
      st.rid, 
      st.date, 
      st.updated,
      stats.total_reviews, 
      stats.total_recommendations,
      GROUP_CONCAT( DISTINCT cat.catid ) categories,
      GROUP_CONCAT( DISTINCT genre.genre_id ) genres,
      GROUP_CONCAT( DISTINCT warn.warning_id ) as warnings
   FROM
      fanfiction_stories_categories cat
         JOIN fanfiction_stories st
            ON cat.sid = st.sid
            AND st.Validated = 1
            LEFT JOIN fanfiction_stories_stats stats 
               ON st.sid = stats.sid
            LEFT JOIN fanfiction_stories_genres genre
               on st.sid = genre.sid
            LEFT JOIN fanfiction_stories_warnings warn
               on st.sid = warn.sid
   WHERE 
      cat.catid = 924
   group by 
      st.sid
   ORDER BY 
      updated DESC
   LIMIT 
      0, 15