我正在建立一个表来管理一些文章:
| Company | Store | Sku | ..OtherColumns.. |
| 1 | 1 | 123 | .. |
| 1 | 2 | 345 | .. |
| 3 | 1 | 123 | .. |
大部分时间公司,商店和sku将用于SELECT行:
SELECT * FROM stock s WHERE s.company = 1 AND s.store = 1 AND s.sku = 123;
..但有时候访问该表时公司将无法使用。
SELECT * FROM stock s WHERE s.store = 1 AND s.sku = 123;
..有时会为商店选择所有文章。
SELECT * FROM stock s WHERE s.company = 1 AND s.store = 1;
如何正确索引表格?
我可以添加三个索引 - 每个选择一个,但我认为oracle应该很聪明地重用其他索引。
如果WHERE条件没有公司,是否会使用Index“Store,Sku,Company”?
如果WHERE条件没有公司,是否会使用索引“公司,商店,Sku”?
答案 0 :(得分:5)
您可以将索引键视为概念上的“串联”键。在所有列中,通常需要具有该键的前导元素才能从索引中获益。所以对于(公司,商店,sku)的索引,那么
WHERE s.company = 1 AND s.store = 1 AND s.sku = 123;
可能会从索引中受益
WHERE s.store = 1 AND s.sku = 123;
不太可能受益(但请参阅下面的脚注)
WHERE s.company = 1 AND s.store = 1;
可能会从索引中受益。
在所有情况下,我说"潜在"等等,因为它是优化器的成本决策。例如,如果我只有(比方说)2家公司和2家商店,那么对公司和商店进行查询,而可能使用索引可能更适合而不是这样做,因为要查询的信息量仍然是表格大小的一小部分。
在您的示例中,可能是(store,sku,company)上的索引将足够好"满足所有三个,但这取决于数据的分布。但是你正在思考正确的方法,即从尽可能少的索引中获取尽可能多的价值。
脚注:有一种叫做"跳过扫描"即使您没有指定前导列,我们也可以从索引获取值,但是通常只会看到那些前导列中的不同值的数量很少。
答案 1 :(得分:0)
首先 - 你需要索引吗?索引不是免费的。如果你的桌子很小,或许你根本不需要索引。
第二 - 什么是数据结构?你在每个场景中都有商店专栏 - 我可以想象商店中的过滤数据分析源数据的程度足以让你足够好。
但是,如果您希望获得最大的合理性能优势,则需要两个:
(商店,sku,公司)
(商店,公司)
或
(商店,公司,sku)
(store,sku)
Would an Index "Store, Sku, Company" be used if the WHERE-condition has no company?
是
Would an Index "Company, Store, Sku" be used if the WHERE-condition has no company?
可能不是,但我可以想象它可能发生的场景(不是索引搜索操作,这实际上是索引的主要目的)
您按列顺序剖析数据。因此,您按第一个元素对数据进行分组,并按照第一列排序顺序对它们进行排序,然后在这些组中按第二个元素的相同方式进行分组 因此,当您不在过滤中使用索引的第一个元素时,数据库必须访问所有"子组"反正。
我建议一般阅读索引。从https://en.wikipedia.org/wiki/B-tree开始,尝试绘制它在纸上的行为或编写简单程序来管理简化版本。然后阅读数据库中的索引 - 任何数据库都足够好。