Azure 通知我,由于 ORDER BY 子句,我的查询性能不佳,添加复合索引将大大受益。我已经阅读了大量内容,并反复尝试为此查询添加复合索引,但不幸的是,我的尝试要么没有任何改进,要么为查询的 RU 略有增加。
我的查询有以下内容:
WHERE
p.BusinessId = 'id' AND
p.PurchaseDate >= '2018-07-04T16:26:42.0882176-06:00' AND p.PurchaseDate < '2023-07-10T15:26:42.0882176-06:00' AND
NOT Contains(LOWER(p.TransactionIdentifier), 'history')
ORDER BY p.PurchaseDate DESC
根据我所做的所有阅读,我应该有两个复合索引,一个(businessId,purchaseDate 降序)和一个(businessId,transactionIdentifier)。因为每个复合索引只能有一个范围或函数,而我有两个,所以我需要两个索引。然而,这不起作用,因为它提示没有匹配的复合索引。它唯一不会提示的配置是(businessId、purchaseDate 降序、transactionIdentifer),这实际上增加了运行查询所需的 RU。
文档还指出,我应该将这些过滤器包含在 ORDER BY 中以提高性能。我也尝试过添加这些。似乎没有什么能让我减少 RU。
我一直在尝试遵循以下资源,但没有取得进展:
- https://learn.microsoft.com/en-us/azure/cosmos-db/index-policy
- https://willvelida.medium.com/understanding-indexing-in-azure-cosmos-db-62299c351a19
- https://learn.microsoft.com/en-us/azure/cosmos-db/index-overview
- https://devblogs.microsoft.com/cosmosdb/new-ways-to-use-composite-indexes/
我被困住了。谁能帮我找出该查询的正确复合索引配置?
最佳答案
原因
我很确定这种情况不能利用索引:
NOT Contains(LOWER(p.TransactionIdentifier), 'history')
来自 LOWER
function documentation :
- This function doesn't use the index.
- If you plan to do frequent case insensitive comparisons, this function may consume a significant number of RUs. Consider normalizing the casing of strings when ingesting your data. Then a query like SELECT * FROM c WHERE LOWER(c.name) = 'USERNAME' is simplified to SELECT * FROM c WHERE c.name = 'USERNAME'.
旁注,您不必显式使用 TOLOWER,see CONTAINS
function :
CONTAINS(<string_expr_1>, <string_expr_2> [, <bool_expr>])
bool_expr (Optional) - Optional boolean value for ignoring case. When set to true, CONTAINS performs a case-insensitive search. When unspecified, this value defaults to false.
Remarks又传来坏消息:
This function performs a full scan.
虽然我已经看到这些函数能够利用索引的提示(请参阅 here ),但文档目前另有说法。不管怎样,你也有 NOT
无论如何,这可能会破坏交易。
因此 - 没有为此使用索引。
你能做什么
重新思考您的数据模型
即预先计算 bool 值 IsTransactionHistory
或与您的模型类似,高效的索引选项会亮起。
这是获得良好性能且没有拖累负担的首选方法。
排除 TransactionIdentifier
来自该索引。
因为它无法使用,只会使索引变得更大并且匹配更少=成本更高。
您最好的选择很可能是 (p.BusinessId, p.PurchaseDate)
上的更简单的索引.
根据数据基数和参数模式,我还会在 PurchaseDate
上尝试更简单的索引。如果您查询的日期范围非常窄并且错误很少,它可能会更好 BusinessId
-s 在切片中。
忽略它。
有时,忽略效率低下并购买少量额外的 RU 在经济上是可行的。很少,但算一下。
关于azure - Cosmos db 的复合索引没有改善 RU 使用率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76662707/