【问题标题】:Double Inner Join Too Slow双内连接太慢
【发布时间】:2015-03-02 16:39:46
【问题描述】:

嘿,我环顾四周,找不到解决问题的方法。 我有一个有 3 个表格的营养数据库。所有 3 个表格都有单个项目的名称、营养成分和测量单位。我想退回单一营养素含量最高的物品,即。蛋白质。

我当前的查询大约需要 3 秒才能获得条目,这将是一个问题,因为我将在一个页面中多次针对多种营养素进行此查询。任何帮助表示赞赏。

food_des - about 8,000 entries
+-------+---------+--------+
|NDB_No |Long_Desc|Fd_Group|
+-------+---------+--------+
|01001  |Banana   |0100    |
|01002  |Apple    |0102    |
+-------+---------+--------+

nut_data - about 600,000 entries
+-------+-------+--------+
|NDB_No |Nutr_No|Nutr_Val|
+-------+-------+--------+
|01001  |318    |55.5    |
|01001  |320    |1.1     |
|01002  |318    |30.2    |
|01002  |325    |12.3    |
+-------+-------+--------+

nut_def - about 150 entries
+-------+--------+-----+
|Nutr_No|NutrDesc|Units|
+-------+--------+-----+
|318    |Carbs   |g    |
|319    |Energy  |kcal |
|320    |Protein |g    |
|325    |Iron    |mg   |
+-------+--------+-----+

SELECT food_des.Long_Desc, nut_data.Nutr_Val, nutr_def.Units
FROM food_des
INNER JOIN nut_data
ON food_des.NDB_No=nut_data.NDB_No
INNER JOIN nutr_def
ON nut_data.Nutr_No=nutr_def.Nutr_No
WHERE nutr_def.NutrDesc="Vitamin D" 
ORDER BY Nutr_Val DESC
LIMIT 5

【问题讨论】:

  • 您在表上定义了哪些索引?
  • 抱歉,表 food_des 中唯一的索引是 NDB_No
  • 你真的应该索引nut_data:我建议至少在(NDB_No) 上建立一个简单的索引,尽管最佳方法可能包括在(NDB_No, Nutr_No) 上的复合以及nutr_def.Nutr_No 上的索引。如果之后您发现性能仍然无法接受,请发布您的执行计划(“EXPLAIN SELECT ...”),我们可以考虑添加一些覆盖索引。
  • @eggyal: 也索引nutr_def.NutrDesc--用在 WHERE 子句中。
  • 哇!现在下降到 0.8-1 秒!我还能做些什么来加快速度吗?

标签: mysql performance inner-join


【解决方案1】:

WHERE nutr_def.NutrDesc="Vitamin D" 请求INDEX(NutrDesc)。所以,假设优化器从 nutr_def 开始,那么它需要转到 nut_data,这需要INDEX(Nutr_No),然后是 food_des,需要INDEX(NDB_No)

如果优化器选择从 ORDER BY 开始,那么INDEX(Nutr_Val) 将是有益的。 (请在使用 JOIN 时限定字段!我们无法判断它在哪个表中!)因此,如果它以该表开头,请按照 JOIN 来查看其他两个表需要哪些索引。

如果您需要进一步讨论,请提供SHOW CREATE TABLEEXPLAIN SELECT...

【讨论】:

    【解决方案2】:

    运行这个

    EXPLAIN SELECT food_des.Long_Desc, nut_data.Nutr_Val, nutr_def.Units
    FROM food_des INNER JOIN nut_data
    ON food_des.NDB_No=nut_data.NDB_No
    INNER JOIN nutr_def
    ON nut_data.Nutr_No=nutr_def.Nutr_No
    WHERE nutr_def.NutrDesc="Vitamin D" 
    ORDER BY Nutr_Val DESC
    LIMIT 5
    

    然后决定要在哪里添加索引

    【讨论】:

    • 我得到了 select_type|table|type|possible_keys|key|key_len|ref|rows SIMPLE|nutr_def|ref|PRIMARY,NutrDesc|NutrDesc|62|const|2 SIMPLE|food_des|ALL|PRIMARY| NULL|NULL|NULL|7771 SIMPLE|nut_data|eq_ref|PRIMARY,NDB_No|PRIMARY|12|info.food_des.NDB_No,info.nutr_def.Nutr_No|1 抱歉,看起来有点乱
    • 看起来您在 food_des 上还没有 INDEX(NDB_No)。
    猜你喜欢
    • 2013-03-25
    • 1970-01-01
    • 1970-01-01
    • 2012-02-13
    • 1970-01-01
    • 1970-01-01
    • 2012-06-22
    • 2015-12-30
    • 1970-01-01
    相关资源
    最近更新 更多