Mysql大表连接查询非常慢而不是密钥索引问题

时间:2015-08-29 06:20:02

标签: mysql query-performance

SELECT  t1.*
    FROM  
      ( SELECT  key_a,key_b,MAX(date) as date
            FROM  large_table
            WHERE  date <= **20150126**
            group by  key_a,key_b 
      ) AS t2
    JOIN  large_table AS t1 USING(key_a,key_b ,date) 
  

large_table = 1,223,001,206行数据

Primary Key key_a,key_b,date
key on key_b
key on date

&amp;行之间有许多空日期。 b我想要最近的后面或“日期”输入。

是Mysql Join设置导致它变慢吗?

我可以复制整套 a&amp; b 只有通过选择所有行然后在临时表上执行INSERT到临时表的数据,但为什么在只需要1时进行多个查询(插入选中,然后选择)。 / p>

上面的查询在临时插入所有日期表中只有4,128,548个总结果,特定日期返回总计180,000以下。

不是表优化,而不是键,是最大排序长度,加入缓冲区大小,我有128 gig ram,在运行这个的32核服务器上,没有理由让它变慢,只是从不批量插入这个大运行单个表的连接如果其他人已经处理了这个大小的表任何信息,请加入先前的查询。

编辑过的查询,是的,在不需要的时候或实际查询中已经很长的一天

1 个答案:

答案 0 :(得分:0)

        WHERE  date <= **20150126**
        group by  key_a,key_b 

需要使用date启动的索引。它是关于使用WHERE子句做的事情,而不是稀疏或密集。

然后......由于内部查询仅引用了3列,因此构建了一个&#39;覆盖&#39;索引可能有用。 (在您的情况下可能很有用。)因此,以任何顺序处理其他两个字段。如

INDEX(`date`, key_a, key_b)

对于MyISAM,这一步至关重要。对于InnoDB,这是多余的,因为每个辅助密钥(例如您的INDEX(date))隐含地包含PK的其余字段。

不,PRIMARY KEY(key_a, key_b, date)不能达到目的。它的顺序错误。此外,它是(如果您使用InnoDB)&#34;集群&#34;与索引。

  

上面的查询在临时插入所有日期表中只有4,128,548个总结果,特定日期返回总计180,000以下。

抱歉,我无法解析它。我假设你说4M行有&#39; date&lt; ...&#39;子查询只传递180K行。因此,外部查询也返回180K行。

第一个目标是尽可能有效地通过4M行。根据我提出的索引,可能是大约20K块(每个16KB)的索引扫描。那是300MB。

接下来执行MAXGROUP BY。在300MB时,这将涉及磁盘tmp表。 (请参阅max_heap_sizemax_tmp_table_size。)

然后JOIN来获取t1.*。您正在使用一种很好的技术从一个巨大的表中获取一堆行,您需要GROUP BY(或LIMIT或...),这在显而易见的情况下是笨拙的。它是这样的:编写子查询来查找PK。获得最佳索引。然后在PK上JOIN

现在为JOIN。 (再次,我假设InnoDB。)由于您在PK上JOINing,每次查找t1都会有效 - 深入了解PK的BTree以找到一行。这样做180K次。

如果这些180K查找分散在表中,那么可能是180K磁盘命中。

总努力:20K + 180K = 200K磁盘命中,可能更少。在商品旋转磁盘上,这将花费大约30 分钟(加上tmp表的时间)。 (不,只会使用一个核心。无论如何,I / O可能是瓶颈。)

OPTIMIZE TABLE - 几乎总是没用。

我认为innodb_buffer_pool_size约为90G?如果事情将被缓存,那就是它会发生的地方(对于InnoDB)。由于200K块是3GB,因此可以轻松缓存。也就是说,如果您运行查询两次,第一次可能是30分钟,但第二次可能不到3分钟。

要获得更多数字,您可以这样做:

FLUSH STATUS;
SELECT ...;
SHOW SESSION STATUS;

并寻找&#39; Handler%&#39;,&#39;%sort%&#39;,&#39; Innodb%&#39;也许还有其他几个。

你在运行什么版本?最近的版本有一个蛙跳技术,对于max + groupby比我描述的更好。我认为它被称为MRR。如果是这样,你的PK实际上是最佳的。 (嗯......我应该玩弄它。)

PARTITIONing - 我没有看到任何好处(针对此查询)。