复合主键和基数

5
我有关于复合主键和列的基数的一些问题。我在网上搜索了很多,但没有找到确切的答案,所以我想再试一次。这些问题是:
背景:大型(50M-500M行)OLAP准备表,不是NOSQL,也不是Columnar。使用MySQL和DB2。
1)PK中的键的顺序是否重要?
2)如果列的基数差异很大,应该先使用哪个。例如,如果我有CLIENT/CAMPAIGN/PROGRAM,其中CLIENT的基数很高,CAMPAIGN适中,PROGRAM几乎像位图索引,最好的顺序是什么?
3)如果有Where子句,那么Join的最佳顺序是什么?当视图中没有Where子句时呢?
提前致谢。
2个回答

3
您有 "MySQL和DB2"。这个答案是针对DB2的,MySQL没有这种情况。
当然,这很合乎逻辑,但优化器考虑的不仅仅是这些。
通常,在WHERE子句(连接)中列的顺序并不重要(也不应该重要)。
然而,与谓词顺序有关的两个项目可能是您提出问题的原因。
1. 重要的是,在处理WHERE子句的索引中的列的顺序。是的,在这里最好按最高基数到最低的顺序指定列。这允许优化器定位更小范围的行。
2. 连接表的顺序(不是连接中的列)非常重要,这可能是最重要的考虑因素。事实上,Join Transitive Closure是自动的,优化器评估所有可能的连接顺序,并根据统计信息选择它认为最好的顺序(这就是为什么UPDATE STATS如此重要的原因)。
无论表中有多少行,如果您从具有错误索引的table_A中加入100行,并且在具有良好索引的table_B中加入了1,000,000行,则希望使用A:B而不是B:A。如果您的IOPS低于最大值,则可能需要采取一些措施。
正确的步骤顺序是:
- 检查索引是否正确,如(1)所述。不要只添加另一个索引,请更正您拥有的索引。 - 检查定期执行更新统计信息。 - 首先尝试优化器的默认操作。设置统计信息并测量I / O。使用代表生产中用户将使用的值集。 - 检查showplan,以确保代码正确。当然,这也会识别出选择的连接顺序。 - 如果性能不够好,并且您认为优化器为这些集合选择的连接顺序是次优的,则关闭JTC OFF(语法取决于您的DB2版本),然后在WHERE子句中指定您想要的顺序。测量I / O。使用代表性集 - 形成意见。选择整体性能更好的那个。永远不要为单个查询进行调整。

2

1) 主键中的键的顺序是否重要?

是的,它会改变用于约束主键的索引记录的顺序。

2) 如果列的基数差异很大,应该先使用哪个。例如,如果我有CLIENT/CAMPAIGN/PROGRAM,其中CLIENT的基数很高,CAMPAIGN适中,PROGRAM几乎像位图索引,最好的顺序是什么?

对于选择查询,这完全取决于您将要使用的查询。如果您同时搜索三个列,则顺序不重要;如果您只搜索两个或一个列,则它们应该在索引中处于领先地位。

对于插入操作,最好使领先的列与记录插入的顺序相匹配。

3) 如果有Where子句和没有Where子句(用于视图)时,Join的最佳顺序是什么?

同样,这取决于WHERE子句。


谢谢,所以如果我只在CLIENT和CAMPAIGN上进行连接,我应该先在CAMPAIGN(低基数)上进行连接,然后再在CLIENT(高基数)上进行连接。 - srini.venigalla
再次感谢,如果谓词顺序不重要,您能否详细说明一下您的语句“取决于WHERE子句”是如何影响计划的。实际上一个URL就可以了。 - srini.venigalla
@srini:计划取决于在连接中使用哪些列,而不是使用哪个顺序。 - Quassnoi
1
@Quassnoi:谢谢,我正在阅读你的其他答案——真是一次很好的学习。但是,难道不是合乎逻辑的假设,我会首先使用最狭窄的谓词(即具有最高基数的索引),然后是下一个更高的基数,以此类推吗? - srini.venigalla
@srini:优化器会自动处理这个问题。 - Quassnoi
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接