Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySQL-distinct+;排序查询性能问题 问题_Mysql_Performance - Fatal编程技术网

MySQL-distinct+;排序查询性能问题 问题

MySQL-distinct+;排序查询性能问题 问题,mysql,performance,Mysql,Performance,以下查询的运行时间超过30秒,除非: 我删除排序(查询),然后让我们检查索引 在bookeditems中是否有关于会议id和项目类型的综合索引 您是否有会议id上的索引?如果它位于复合键中,它是第一个索引吗 你们有关于会议日期时间的聚集索引吗 您是否可以放置一个子查询来获取每个会议id的堆栈顶部,而不是执行distinct 比如: select * from meetings a where datetime = (select max(datetime) from meetings whe

以下查询的运行时间超过30秒,除非:


  • 我删除排序(查询),然后让我们检查索引

    在bookeditems中是否有关于会议id和项目类型的综合索引

    您是否有会议id上的索引?如果它位于复合键中,它是第一个索引吗

    你们有关于会议日期时间的聚集索引吗

    您是否可以放置一个子查询来获取每个会议id的堆栈顶部,而不是执行distinct

    比如:

    select * from meetings a
    where datetime = (select max(datetime) from meetings 
    where meetingid = a.meetingid)
    

    您可以使用会议类型上的case语句来获取相同的数据,而不是左键联接吗?

    我认为index2是不必要的,可以删除;它是index1的前缀。不过,这不会减少查询时间


    解释输出显示了真正的罪魁祸首:“使用临时文件,使用文件排序”。有时,您可以通过让MySQL使用用于连接的相同键执行排序来避免这种情况。如果您将index1更改为(meeting_id,datetime),它可能可以这样做。如果您需要在index1中保留项目类型,您可以将其添加为索引中的第三列,或者在查询中包含一个包含所有值的in()子句。

    您可以尝试帮助优化器首先选择感兴趣的记录(使用
    ORDER by
    LIMIT
    ),然后使用该结果与其他表联接。使用此方法,
    datetime
    上的索引可完全用于
    ORDER BY
    LIMIT
    -子句。此方法如下所示:

    SELECT
      `meetings`.`id` AS `meeting_id`,
      `meetings`.`uid` AS meeting_uid,
      GROUP_CONCAT(
       DISTINCT CASE bookeditems.item_type
         WHEN 'SER' THEN bookeditems.id
         ELSE NULL
       END
      ) AS meetings_SERV_ids,
      GROUP_CONCAT(
       DISTINCT CASE bookeditems.item_type
         WHEN 'TRA' THEN bookeditems.id
         ELSE NULL
       END
      ) AS meetings_TRANSP_ids,
      GROUP_CONCAT(
       DISTINCT CASE bookeditems.item_type
         WHEN 'ACC' THEN bookeditems.id
         ELSE NULL
       END
      ) AS meetings_ACCO_ids,
      GROUP_CONCAT(bookeditems.id) AS meetings_BOOKEDITEMS_ids
    FROM (
      SELECT id
      FROM meetings
      ORDER BY `datetime`
      LIMIT 0, 50
    ) filtered_meetings
    INNER JOIN meetings
      ON meetings.id = filtered_meetings.id
    LEFT OUTER JOIN bookeditems
      ON meeting_uid = bookeditems.meeting_uid
    GROUP BY meeting_uid
    
    显著差异:

    • 我们只加入一次booked items表。在select语句中,我们使用
      GROUP_CONCAT
      CASE
      语句来选择会议组中符合特定条件的所有ID。此外,为了实现这一点,我们需要添加
      GROUP BY
      语句来对代表相同会议的所有行进行分组ng.

      这意味着我们可能会获得
      会议服务ID
      会议传输ID
      会议帐户ID
      会议BOOKEDITEMS\u ID
      的一系列ID。因此,请记住在处理结果行的客户端代码中使用
      分解
      ,或等效的方法

    Order by
    语句总是会大大减慢查询速度。此外,您还可以删除
    meeting
    表上的别名,因为使用别名会强制MySQL查看表上的所有字段。您还可以粘贴查询的
    explain
    的输出吗?即:
    explain SELECT…
    。这将帮助我们了解查询是如何执行的执行计划的外观和使用的索引。请尝试在
    (项目类型,会议id)
    上添加索引。您的表是InnoDB还是MyISAM?@ypercube它已经将其作为索引(我更新了查询,以便会议id现在符合uid);Innodby composite我想你是指包含这两个字段的索引?答:是的,我在meetings表中有关于meeting id的索引。我不知道什么是聚集索引,也不知道如何在MySQL中创建聚集索引-在回答taht之前,我必须先通读一遍。我不明白你所建议的子查询想要实现什么?我怎么不知道是的,如果你是这个意思的话,我可以做一个案例陈述,让bookeditem类型出现在meetings表中…这就是原始查询的功能-我去掉了它以避免复杂性谢谢你的建议-我会尝试它们。问题是datetime并不是唯一可以排序的列,而是唯一可以排序的列我经常重复。此外,为了清楚起见,我更新了问题,将所有表中的索引包括在内。您可以使用MySQL的评测来验证罪魁祸首。运行
    SET profiling=1
    ,然后运行您的查询,然后
    SHOW PROFILES
    ,找到您的查询,然后
    SHOW PROFILE for query n
    。最后一个命令将生成一个精细gra表已定义执行查询所需的步骤,以及每个步骤所需的时间。结果是,磁盘上的复制到tmp表的时间=28.3秒…我已将完整结果包含在问题中。谢谢!我在配置中添加了max_heap_table_size=256M和tmp_table_size=256M,这导致“磁盘上的复制到tmp表的时间=28.3秒”替换为“复制到tmp表,2.27”;但我仍然不高兴这是我所能做的一切(当10个ppl同时命中它时,会发生什么情况-你吸收了2.5G的RAM?)。请让我知道您的想法。还有什么我缺少/可以做的吗?理想情况下,我希望不需要临时表?我发现很难相信查询需要“…ORDER BY…LIMIT N”查询经常遇到这个问题。您当前的查询需要MySQL到1)将结果限制为满足WHERE限制的行,2)对所有行进行排序,3)返回前N个结果。诀窍是修改查询或模式,以允许使用相同的索引进行限制和排序。通过这种方式,MySQL可以避免在对所有结果进行排序之前查找所有满足限制的结果。相反,它保留的结果集要小得多,并且能够在处理行时更新这些结果。这并不总是容易的。事实上,这比原始查询(现在排序16秒)需要更长的时间来执行。我已经用createtable定义更新了这个问题,并添加了为什么我想要像我一样的相关表&而不是像你建议的那样在单个字段中串联ID列表。我意识到我比我想象的更像一个noob!对不起,这是我的想法,没有任何测试表和数据。另外,你可以发布一些样本(期望的)输出。我不太明白你想要的输出格式我不太明白你的问题。。。为了让您了解我想要的输出格式,我需要包含解决方案中的SQL语句(20-30个字段)。我想要一个大学就够了吗
    id | select_type | table                | type | possible_keys      | key         | key_len | ref                      | rows | Extra
    -------------------------------------------------------------------------------------------------------------------------------------
    1  | SIMPLE      | meetings             | ALL  | NULL               | NULL        | NULL    | NULL                     | 7483 | Using temporary; Using filesort
    1  | SIMPLE      | meetings_SERV        | ref  | meeting_uid,index1 | meeting_uid | 767     | test.meetings.uid        | 1    | 
    1  | SIMPLE      | meetings_TRANSP      | ref  | meeting_uid,index1 | meeting_uid | 767     | test.meetings.uid        | 1    | 
    1  | SIMPLE      | meetings_ACCO        | ref  | meeting_uid,index1 | meeting_uid | 767     | test.meetings.uid        | 1    | 
    1  | SIMPLE      | meetings_BOOKEDITEMS | ref  | meeting_uid,index1 | meeting_uid | 767     | test.meetings.uid        | 1    | 
    
    starting                      0.000092
    checking permissions          0.000003
    checking permissions          0.000002
    checking permissions          0.000001
    checking permissions          0.000001
    checking permissions          0.000003
    Opening tables                0.000036
    System lock                   0.000008
    init                          0.000033
    optimizing                    0.000005
    statistics                    0.000035
    preparing                     0.000019
    Creating tmp table            0.000165
    executing                     0.000004
    Copying to tmp table          1.790968
    converting HEAP to MyISAM     1.669041
    Copying to tmp table on disk  28.32606
    Sorting result                0.141737
    Sending data                  0.000099
    end                           0.000005
    removing tmp table            0.022097
    end                           0.000014
    query end                     0.000008
    closing tables                0.000017
    freeing items                 0.000779
    logging slow query            0.000004
    cleaning up                   0.000005
    
    ...
    executing                     0.000004
    Copying to tmp table          1.790968
    Sorting result                0.141737
    ...
    
    select * from meetings a
    where datetime = (select max(datetime) from meetings 
    where meetingid = a.meetingid)
    
    SELECT
      `meetings`.`id` AS `meeting_id`,
      `meetings`.`uid` AS meeting_uid,
      GROUP_CONCAT(
       DISTINCT CASE bookeditems.item_type
         WHEN 'SER' THEN bookeditems.id
         ELSE NULL
       END
      ) AS meetings_SERV_ids,
      GROUP_CONCAT(
       DISTINCT CASE bookeditems.item_type
         WHEN 'TRA' THEN bookeditems.id
         ELSE NULL
       END
      ) AS meetings_TRANSP_ids,
      GROUP_CONCAT(
       DISTINCT CASE bookeditems.item_type
         WHEN 'ACC' THEN bookeditems.id
         ELSE NULL
       END
      ) AS meetings_ACCO_ids,
      GROUP_CONCAT(bookeditems.id) AS meetings_BOOKEDITEMS_ids
    FROM (
      SELECT id
      FROM meetings
      ORDER BY `datetime`
      LIMIT 0, 50
    ) filtered_meetings
    INNER JOIN meetings
      ON meetings.id = filtered_meetings.id
    LEFT OUTER JOIN bookeditems
      ON meeting_uid = bookeditems.meeting_uid
    GROUP BY meeting_uid