使用多个JOIN进行查询优化

时间:2013-01-30 14:21:33

标签: mysql performance join query-optimization star-schema

我对事实表有查询" foo_success"在星型模式中,它有大约600万行。此表保存对维度表的(整数)引用,而不包含任何其他内容。我们使用MyISAM作为存储引擎。

查询:

SELECT 
hierarchy.level0name,
hierarchy.level1name,
hierarchy.level0,
hierarchy.level1,
date.date,
address.city,
user.emailAddress,
foo_object.name,
foo_object.type,
user_group.groupId,
COUNT(user.id) AS count_user_id,
SUM(foo_object_statistic.passes) AS sum_foo_object_statistic_passes,
SUM(foo_object_statistic.starts) AS sum_foo_object_statistic_starts,
SUM(foo_object_statistic.calls) AS sum_foo_object_statistic_calls

FROM 
foo_success,
user,
user_group,
address, 
hierarchy,
foo_object,
foo_object_statistic,
date

WHERE (foo_success.userDimensionId = user.id)
AND (foo_success.userGroupDimensionId = user_group.id)
AND (foo_success.addressDimensionId = address.id)
AND (foo_success.hierarchyDimensionId = hierarchy.id)
AND (foo_success.fooObjectDimensionId = foo_object.id)
AND (foo_success.fooObjectStatisticDimensionId = foo_object_statistic.id)
AND (foo_success.dateDimensionId=date.id)
AND hierarchy.level0 = 'XYZ'
AND hierarchy.level1 IS NOT NULL 
AND hierarchy.level2 IS NOT NULL 
AND hierarchy.level3 IS NOT NULL 
AND hierarchy.level4 IS NOT NULL 
AND hierarchy.level5 IS NOT NULL 
AND hierarchy.level6 IS NULL 
AND hierarchy.level7 IS NULL
GROUP BY hierarchy.level0, foo_object.fooObjectId
LIMIT 0, 25;

到目前为止我已尝试过:

  • 这是简单的连接版本,它等于速度的INNER JOIN替代版本。
  • 所有字段都有连接的索引或属于条件的一部分。
  • 我对此查询使用了EXPLAIN,发现表用户的查询成本(已处理行数)为128596,表foo_success为77。
  • 我尝试删除对用户表的依赖,这导致事实表foo_success中超过600万的已处理行数。

完成此查询大约需要1.5分钟,这远远超出了我对读取速度优化的数据仓库星型模式的期望。有什么方法可以优化这个怪物吗?

1 个答案:

答案 0 :(得分:2)

查询的低效率主要来自传输大量您实际未使用的数据:hierarchy.level1name, hierarchy.level0name, hierarchy.level1, date.date, address.city, user.emailAddress, foo_object.name, foo_object.type, user_group.groupId子句中不包含字段GROUP BY,这意味着每行都会检索信息,加载到内存中然后丢弃。

我建议的是在子查询中集中检索所有足够的id和聚合结果,然后加入其余表,这样每个连接只能产生一行(你甚至可以移动{子查询中的{1}}子句,用于最小化所需的后续JOIN操作)。之后,您可能会发现,您没有一些有用的索引。