2017-05-30 95 views
0

我有一个怪异的情况正在进行。我的一个夜间查询,通常需要5分钟,耗时> 12小时。下面是该查询:MySql - Innodb - 腐败索引/外键

SELECT Z.id, 
     Z.seoAlias, 
     GROUP_CONCAT(DISTINCT LOWER(A.include)) AS include, 
     GROUP_CONCAT(DISTINCT LOWER(A.exclude)) AS exclude 
FROM df_productsbystore   AS X 
INNER JOIN df_product_variants AS Y ON Y.id = X.id_variant 
INNER JOIN df_products   AS Z ON Z.id = Y.id_product 
INNER JOIN df_advertisers  AS A ON A.id = X.id_store 
WHERE X.isActive > 0 
AND Z.id > 60301433 
GROUP BY Z.id 
ORDER BY Z.id 
LIMIT 45000; 

我跑的解释并得到如下:

+----+-------------+-------+--------+------------------------------------------------------------------------------------+-----------+---------+---------------------+------+---------------------------------+ 
| id | select_type | table | type | possible_keys                  | key  | key_len | ref     | rows | Extra       | 
+----+-------------+-------+--------+------------------------------------------------------------------------------------+-----------+---------+---------------------+------+---------------------------------+ 
| 1 | SIMPLE  | A  | ALL | PRIMARY                   | NULL  | NULL | NULL    | 365 | Using temporary; Using filesort | 
| 1 | SIMPLE  | X  | ref | UNIQUE_variantAndStore,idx_isActive,idx_store          | idx_store | 4  | foenix.A.id   | 600 | Using where      | 
| 1 | SIMPLE  | Y  | eq_ref | PRIMARY,UNIQUE,idx_prod               | PRIMARY | 4  | foenix.X.id_variant | 1 | Using where      | 
| 1 | SIMPLE  | Z  | eq_ref | PRIMARY,UNIQUE_prods_seoAlias,idx_brand,idx_gender2,fk_df_products_id_category_idx | PRIMARY | 4  | foenix.Y.id_product | 1 | NULL       | 
+----+-------------+-------+--------+------------------------------------------------------------------------------------+-----------+---------+---------------------+------+---------------------------------+ 

哪个看着我的开发环境不同。该df_advertisers部分看起来腥我,所以我删除并重新创建的X.id_store列的索引,而现在的EXPLAIN这个样子的,查询快捷又是:

+----+-------------+-------+--------+------------------------------------------------------------------------------------+------------------------+---------+-------------------+---------+-------------+ 
| id | select_type | table | type | possible_keys                  | key     | key_len | ref    | rows | Extra  | 
+----+-------------+-------+--------+------------------------------------------------------------------------------------+------------------------+---------+-------------------+---------+-------------+ 
| 1 | SIMPLE  | Z  | range | PRIMARY,UNIQUE_prods_seoAlias,idx_brand,idx_gender2,fk_df_products_id_category_idx | PRIMARY    | 4  | NULL    | 2090691 | Using where | 
| 1 | SIMPLE  | Y  | ref | PRIMARY,UNIQUE,idx_prod               | UNIQUE     | 4  | foenix.Z.id  |  1 | Using index | 
| 1 | SIMPLE  | X  | ref | UNIQUE_variantAndStore,idx_isActive,idx_id_store         | UNIQUE_variantAndStore | 4  | foenix.Y.id  |  1 | Using where | 
| 1 | SIMPLE  | A  | eq_ref | PRIMARY                   | PRIMARY    | 4  | foenix.X.id_store |  1 | NULL  | 
+----+-------------+-------+--------+------------------------------------------------------------------------------------+------------------------+---------+-------------------+---------+-------------+ 

这样看来,该指数奇迹般地消失了。任何人都可以解释这是可能的吗?我的意思是定期运行mysqlcheck命令或类似命令以避免这种情况?我很难过!

感谢

回答

1

下一次,简单地做ANALYZE TABLE df_productsbystore;这将是非常快的,并且可以解决问题。

ANALYZE重新计算优化程序所依据的统计信息,以决定在此情况下决定使用哪个表。在极少数情况下,统计数据会过时并需要在小腿上踢球。

警告:我假设你在最近的版本上使用InnoDB。如果您使用的是MyISAM,则更经常需要ANALYZE

你真的需要45K行吗?你会怎么做这么多?

的一种方式,以加快查询了(可能)是做,一切可以用X和Z子查询然后JOIN A做休息:

SELECT XYZ.id, XYZ.seoAlias, 
     GROUP_CONCAT(DISTINCT LOWER(A.include)) AS include, 
     GROUP_CONCAT(DISTINCT LOWER(A.exclude)) AS exclude 
    FROM 
    (
     SELECT Z.id, Z.seoAlias, X.id_store 
      FROM df_productsbystore AS X 
      INNER JOIN df_product_variants AS Y ON Y.id = X.id_variant 
      INNER JOIN df_products AS Z   ON Z.id = Y.id_product 
      WHERE X.isActive > 0 
       AND Z.id > 60301433 
      GROUP BY Z.id -- may not be necessary ?? 
      ORDER BY Z.id 
      LIMIT 45000 
    ) AS XYZ 
    INNER JOIN df_advertisers AS A ON A.id = XYZ.id_store 
    GROUP BY ZYZ.id 
    ORDER BY XYZ.id; 

有用的指标:

Y: INDEX(id_product, id) 
X: INDEX(id_variant, isActive, id_store) 
+0

嗨里克,感谢您的职位。 ANALYZE似乎没有工作,我认为我们的数据库是搞砸了: – mils

+0

重新配置的查询,再加上索引没有区别吗? –

+0

嗨瑞克,你重新配置的查询是非常好的。当机器快速运行时,差异很小但随后机器运行速度变慢,查询速度明显加快,我所能想到的只是它与缓存有关,再次感谢。 – mils

0

为了解决这个问题,我尝试删除并重新创建索引+ FK。这并不是第一次解决问题,而是机器处于负载状态,但它在安静的机器上第二次工作。

它只是感觉像MySQL是片状。我真的不知道还有什么要说的。

感谢您的帮助,虽然