Compound Couchbase 4.x 全球二级索引
Compound Couchbase 4.x Global Secondary Indexes
在 Couchbase 4.x 中创建 compound 全局二级索引时,我很好奇基于 CREATE INDEX 语句期间提供的字段排序的性能。
为了说明,让我从一个例子开始:
CREATE INDEX Index_1
ON `bucket`(field1, field2)
USING GSI;
现在当我们执行以下查询时:
SELECT * FROM `bucket`
WHERE `bucket`.field1 = "value1"
AND `bucket`.field2 = "value2";
我很清楚使用 Index1 是显而易见的。但是,有一些情况我不清楚:
- 如果只提供了字段 2 而没有提供字段 1 怎么办?
SELECT * FROM bucket
WHERE bucket
.field2 = "value2";
- 如果WHERE子句中field2和field1的顺序相反怎么办?
SELECT * FROM bucket
WHERE bucket
.field2 = "value2" AND bucket
.field1 = "value1";
我知道这个例子只适用于 2 个字段,但在我的例子中,我有大约 10 个字段。在这种情况下,创建许多索引来涵盖所有可能性似乎是组合爆炸(甚至阶乘,如果您考虑所有可能的排序并且排序很重要)。如果缺少的字段很重要,那就更糟了,因为那样您将需要对可能的字段子集进行所有可能的排序。即[(field1, field2), (field1), (field2, field1), (field2)],这只针对2个字段。
CREATE INDEX
语句中的字段顺序确实很重要。您的查询必须包含前导字段 field1
,但可以选择包含尾随字段。您的索引只有一个尾随字段 field2
。
您的第一个查询将不会使用该索引,因为它缺少前导字段。确保在测试索引时删除主索引或检查计划以确保它不包含 PrimaryScan
。
如第二个示例所示,重新排序查询谓词不会改变索引的使用方式。 IndexScan
中使用所有前导字段,无论它们出现在查询谓词中的什么位置。
但是,如果您有一个包含两个以上字段的索引,例如:
CREATE INDEX Index_2
ON `bucket`(field1, field2, field3, field4)
USING GSI;
并且您的查询排除了第二个字段:
SELECT * FROM `bucket`
WHERE `bucket`.field1 = "value1"
// field2 not specified
AND `bucket`.field3 = "value3";
仅指定了一个前导字段,因此仅使用 field1
谓词扫描索引。查询服务必须完成剩余工作以过滤具有 field3
值的项目。
在 Couchbase 4.x 中创建 compound 全局二级索引时,我很好奇基于 CREATE INDEX 语句期间提供的字段排序的性能。
为了说明,让我从一个例子开始:
CREATE INDEX Index_1
ON `bucket`(field1, field2)
USING GSI;
现在当我们执行以下查询时:
SELECT * FROM `bucket`
WHERE `bucket`.field1 = "value1"
AND `bucket`.field2 = "value2";
我很清楚使用 Index1 是显而易见的。但是,有一些情况我不清楚:
- 如果只提供了字段 2 而没有提供字段 1 怎么办?
SELECT * FROM
bucket
WHEREbucket
.field2 = "value2"; - 如果WHERE子句中field2和field1的顺序相反怎么办?
SELECT * FROM
bucket
WHEREbucket
.field2 = "value2" ANDbucket
.field1 = "value1";
我知道这个例子只适用于 2 个字段,但在我的例子中,我有大约 10 个字段。在这种情况下,创建许多索引来涵盖所有可能性似乎是组合爆炸(甚至阶乘,如果您考虑所有可能的排序并且排序很重要)。如果缺少的字段很重要,那就更糟了,因为那样您将需要对可能的字段子集进行所有可能的排序。即[(field1, field2), (field1), (field2, field1), (field2)],这只针对2个字段。
CREATE INDEX
语句中的字段顺序确实很重要。您的查询必须包含前导字段 field1
,但可以选择包含尾随字段。您的索引只有一个尾随字段 field2
。
您的第一个查询将不会使用该索引,因为它缺少前导字段。确保在测试索引时删除主索引或检查计划以确保它不包含 PrimaryScan
。
如第二个示例所示,重新排序查询谓词不会改变索引的使用方式。 IndexScan
中使用所有前导字段,无论它们出现在查询谓词中的什么位置。
但是,如果您有一个包含两个以上字段的索引,例如:
CREATE INDEX Index_2
ON `bucket`(field1, field2, field3, field4)
USING GSI;
并且您的查询排除了第二个字段:
SELECT * FROM `bucket`
WHERE `bucket`.field1 = "value1"
// field2 not specified
AND `bucket`.field3 = "value3";
仅指定了一个前导字段,因此仅使用 field1
谓词扫描索引。查询服务必须完成剩余工作以过滤具有 field3
值的项目。