一个复合索引还是多个外键索引?

b09cbbtk  于 2021-06-21  发布在  Mysql
关注(0)|答案(5)|浏览(347)

为关系表的所有外键创建一个覆盖索引和为关系表的每列(外键)创建一个索引有什么区别?
例如,我有table sales(p_id, e_id, c_id, ammount) 其中,p\u id是外键(products表),e\u id是外键(employee表),c\u id是外键(customer表)。表的主键是 {p_id, e_id, c_id} . 哪一个更好?

CREATE INDEX cmpindex ON sales(p_id, e_id, c_id)

CREATE INDEX pindex on sales(p_id)
CREATE INDEX eindex on sales(e_id)
CREATE INDEX cindex on sales(c_id)

我主要在关系表和父表上运行带有联接的查询。

brqmpdu1

brqmpdu11#

请注意,只有在查询第一部分、第一部分和第二部分、第一部分、第二部分和第三部分等时,才会使用复合键上的索引,因此查询p\u id或p\u id和e\u id等,甚至e\u id和p\u id都会使用索引。实际上,任何包含p\u id的查询都将使用此索引。但是,如果您在e\u id或c-id或这两者的任意组合上查询sales表,将不使用cmpindex,并将执行完整的表扫描。
在每个外键上都有一个索引(一个非唯一索引,因为可能有同一产品、同一员工或同一客户的多次销售,从而导致索引中的条目重复)的一个好处是,查询优化器可以选择使用索引来减少返回的行数,然后依次搜索结果集。
e、 g.如果查询是搜索特定产品对特定客户(无论员工)的销售额,并且您有一百万销售额,则外键索引cindex可用于向该特定客户返回20个销售项目,结果集可以非常有效地按顺序搜索,以找出哪些销售是针对特定产品的。如果对产品执行搜索并使用pindex,则结果集可能是10000行(该产品的所有销售额),必须依次搜索这些行才能找到该产品对特定客户的销售额,从而导致查询效率非常低。
我相信为一个表(由优化器使用)保存的统计信息可以跟踪使用每个索引的查询将返回的平均行数,因此优化器将能够计算出应该使用cindex而不是上面示例中的pindex。或者,您可以对查询提供提示,以指定要使用的特定索引。显然,定期运行updatestatistics是很重要的,因为如果平均每个产品只有10个销售,那么执行计划将使用上述示例中的pindex。

yfjy0ee7

yfjy0ee72#

如果您的查询(搜索)通过sales为每个表单独传播,那么您必须为每个表创建单独的索引。如果没有必要的话,你可以选择复合材料。

vwkv1x7d

vwkv1x7d3#

正如honeybadger所评论的,您已经有了一个复合索引,因为您的主键本身就是一个索引。
一般来说,每当您认为将有涉及每个字段本身的查询时,应该为每一列使用一个索引。
如这里所述,当您有一个复合索引时,它可以处理涉及所有字段的查询,或者处理涉及第一个字段(按顺序)、第一个和第二个字段,或者第一个、第二个和第三个字段一起的查询。它不会用于只涉及第二和第三个字段的查询。

7bsow1i6

7bsow1i64#

哪一个更好取决于您的实际查询。
有一件事要明白,当你加入这个表格 sales 一旦进入查询,它将只使用一个索引(最多)。因此,您需要确保有一个最适合查询的索引可用。
如果你加入 sales 所有其他三张table( customer , product 以及 employee )然后,最好使用复合索引,假设引擎将实际使用它而不执行表扫描。
当涉及到结果的顺序时,复合索引中字段的顺序很重要。例如,如果您的查询将按产品(第一个)对结果进行分组,然后按客户排序详细信息,那么您可以从一个索引中获益,该索引首先具有产品id,其次是客户id。
但也可能是引擎决定最好开始扫描表 sales 首先,然后使用其他三个表各自的主键索引联接它们。在这种情况下,不会使用 sales table。
找到的唯一方法是获取查询的执行计划,并查看在定义索引时将使用哪些索引。
如果您在 sales 表中,不需要有多个索引。但更可能的是,您有几个查询输出完全不同的结果,具有不同的字段选择、过滤器、分组等。
在这种情况下,您可能需要多个索引,其中一些将用于一种查询类型,而另一些用于其他类型的查询。请注意,您的建议并非相互排斥。您可能会受益于几个复合索引,它们只是具有不同的字段顺序。
显然,大量索引会减慢这些表中的数据更改,因此您还需要考虑这种权衡。

q3aa0525

q3aa05255#

其他答案缺少一个要点。在mysql中声明外键时,它会在列上创建索引。这在其他数据库中(不一定)是正确的,但在mysql中是正确的。
因此,声明会自动创建以下索引:

CREATE INDEX pindex on sales(p_id);
CREATE INDEX eindex on sales(e_id);
CREATE INDEX cindex on sales(c_id);

(这些索引对于处理级联约束和维护基于外键的数据完整性非常方便。)
如果您碰巧还声明了 sales(p_id, e_id, c_id, amount) ,则不需要第一个索引—它是该索引的子集。然而,另外两个是需要的。
是否需要此索引?正如在其他问题中提到的,这取决于要使用索引的查询。我建议从这个主题的文档开始,了解索引是如何使用的。

相关问题