索引覆盖和DB2查寻性能 |
本文标签:DB2 当索引包含查寻中所有的列,我们通常说索引包含查寻,任何时候发生这种情况时,DB2优化器通常选择只访问查寻所需的索引,称为的纯索引访问或索引覆盖 。但“通常”并不意味着“总是” 。例如,让我们考虑下面的图表结构: CREATEINDEXCONTACT_ZIP_PHONEONCONTACT(ZIPCODE,PHONE_NUMBER); CREATEINDEXCONTACT_PHONEONCONTACT(PHONE_NUMBER); Letusconsiderthisquery: SELECTZIPCODE,PHONE_NUMBERFROMCONTACTWHEREPHONE_NUMBERLIKE312987654%ANDZIPCODE=60606 很明显索引CONTACT_ZIP_PHONE并不覆盖查寻,但DB2优化器并没有用它 。而是通过另一个索引“CONTACT_PHONE”来访问这个图表,这使我们有些吃惊,是吧?实际上这个决定很有意义,DB2优化器非常强力地寻找最好的访问计划 。让我们理解为什么DB2优化器的决定确实是好 。一方面,符合条件ZIPCODE=60606的行数超过15,000行,另一方面,符合PHONE_NUMBERLIKE312987654%的行数不超过10行 。这意味着PHONE_NUMBER的条件更有选择性 。有一个著名的经验说法是:“将最有选择性的列放在索引定义的前面” 。让我们对实际执行成本进行仔细的研究,了解这个理论(优化器)是否是对的: 读取了两个索引页面,一个是根索引页面,另一个是叶级别页面 现在DB2优化器在扫描索引CONTACT_ZIP_PHONE的部分,从值60或之后开始,扫描到61,实际执行成本明显高得多 。 扫描多于100个叶级别页面 正如我们看到的,优化器明智地选择不使用覆盖索引 。 现在让我们回到刚才提过的经验说法:“将最有选择性的列放在索引定义的前面”,正如我们所讨论的,在大多数情况下是对的 。但也有几种例外,让我们想象一个例子,为了开始,我们先生成一个在定义中有这种最高选择性的索引 。 SELECTZIPCODE,PHONE_NUMBERFROMCONTACTWHEREZIPCODE=60606 如果让选择这两个索引,DB2优化器将最有可能选择在(ZIPCODE,PHONE_NUMBER)的索引 。在执行过程中,只有索引部分被检查以支持查寻 。如果取消这个索引,DB2数据库引擎将通过检查在(PHONE_NUMBER,ZIPCODE)的整个索引来确保查寻,那样肯定会慢些的 。如果这个查寻经常执行,那采用(ZIPCODE,PHONE_NUMBER)的索引是对的 。 正如我们看到的,经验说法“将最有选择性的列放在索引定义的前面”只是一个建议 。是的,这是很好的建议,在多数情况下它是对的 。但当将最有选择性的列放在索引定义的后面的情况也会发生,在特殊情况下进行仔细的思考做出自己的决定 。 关于作者:AlexanderKuznetsov有15年软件设计,开发和数据库管理的经验 。目前他在改善在数千兆字节数据库环境下运行的应用程序的性能 。Alexander是IBM认证的高级技术专家(群集)和IBM认证解决方案专家(数据库管理和应用开发) 。 读者IudithM写到: 上面所描述的问题里,ZIPCODE列是较少有性质性的,但不是最有选择性的,因为它返还了更高比例的行数 。 当作者认为“将最有选择性的列放在索引定义的前面”只是经验之谈是正确的观点,但不是根据选择性,而是基于图表中不同行的不同具体位置对整体性能的影响的事实 。 在更具选择性列选择比较少选择性列的索引的性能要低 。例如,由第一个索引所返还的“较少”的行会散落到许多数据区中,而由第二个索引返还的“较多”的行将集中在较少的数据区中 。 所以应当对不同的情况在特定环境下进行分别测试 。
|