【发布时间】:2019-01-07 10:53:38
【问题描述】:
您能否为该查询建议可能的 couchbase 索引以及您如何推动您的选择?
SELECT Count(*) AS count
FROM `ORDER`
WHERE `_class` = "com.lbk.entities.OrderEntity"
AND (
lower(buyer.contact.firstname) LIKE '%aziz%'
OR lower(buyer.contact.lastname) LIKE '%aziz%'
OR ANY communicationchannel IN buyer.contact.communicationchannel satisfies ( communicationchannel.communicationchannelcode = 'EMAIL'
AND communicationchannel.communicationvalue = NULL )
END )
AND ordertypecode = '220'
AND (
ordercategory != 'EXCLUDED_CAT'
OR ordercategory IS NOT valued )
AND creationdatetime IN
(
SELECT raw max(o2.creationdatetime)
FROM `ORDER` o2
WHERE (
lower(o2.buyer.contact.firstname) LIKE '%aziz%'
OR lower(o2.buyer.contact.lastname) LIKE '%aziz%'
OR ANY communicationchannel IN o2.buyer.contact.communicationchannel satisfies ( communicationchannel.communicationchannelcode = 'EMAIL'
AND communicationchannel.communicationvalue = NULL )
END )
AND ANY communicationchannel IN o2.buyer.contact.communicationchannel satisfies ( communicationchannel.communicationchannelcode = 'EMAIL'
AND communicationchannel.communicationvalue IS NOT NULL ) END
AND o2.ordertypecode = '220'
AND (
o2.ordercategory != 'EXCLUDED_CAT'
OR o2.ordercategory IS NOT valued)
GROUP BY ( array item.communicationvalue FOR item IN o2.buyer.contact.communicationchannel WHEN item.communicationchannelcode = 'EMAIL'
END )
)
我创建了这个被查询命中的索引:
CREATE INDEX `idx_customer` ON
`order`(`_class`, ((`buyer`.`contact`).`firstname`), ((`buyer`.`contact`).`lastname`), (DISTINCT (array
(`aoc`.`communicationvalue`) FOR `aoc` IN ((`buyer`.`contact`).`communicationchannel`) WHEN
((`aoc`.`communicationchannelcode`) = "EMAIL") end)))
但我的表现很差,与其他反应相对应,这主要是由于我的索引设计不佳。
我的查询的解释是:
{
"plan": {
"#operator": "Sequence",
"~children": [
{
"#operator": "UnionScan",
"scans": [
{
"#operator": "IntersectScan",
"scans": [
{
"#operator": "IndexScan3",
"index": "idx_customer1",
"index_id": "d1463e49b12fcd45",
"index_projection": {
"primary_key": true
},
"keyspace": "order",
"namespace": "default",
"spans": [
{
"range": [
{
"high": "\"220\"",
"inclusion": 3,
"low": "\"220\""
},
{
"inclusion": 0,
"low": "null"
}
]
}
],
"using": "gsi"
},
{
"#operator": "DistinctScan",
"scan": {
"#operator": "IndexScan3",
"index": "idx_customer",
"index_id": "2132a2f8632e76f3",
"index_projection": {
"primary_key": true
},
"keyspace": "order",
"namespace": "default",
"spans": [
{
"range": [
{
"high": "\"com.lbk.entities.OrderEntity\"",
"inclusion": 3,
"low": "\"com.lbk.entities.OrderEntity\""
},
{
"inclusion": 0,
"low": "null"
}
]
}
],
"using": "gsi"
}
}
]
},
{
"#operator": "IndexScan3",
"index": "idx_customer1",
"index_id": "d1463e49b12fcd45",
"index_projection": {
"primary_key": true
},
"keyspace": "order",
"namespace": "default",
"spans": [
{
"range": [
{
"high": "\"220\"",
"inclusion": 3,
"low": "\"220\""
},
{
"inclusion": 0,
"low": "null"
}
]
}
],
"using": "gsi"
}
]
},
{
"#operator": "Fetch",
"keyspace": "order",
"namespace": "default"
},
{
"#operator": "Parallel",
"~child": {
"#operator": "Sequence",
"~children": [
{
"#operator": "Filter",
"condition": "((((((`order`.`_class`) = \"com.lbk.entities.OrderEntity\") and (((lower((((`order`.`buyer`).`contact`).`firstName`)) like \"%aziz%\") or (lower((((`order`.`buyer`).`contact`).`lastName`)) like \"%aziz%\")) or any `communicationChannel` in (((`order`.`buyer`).`contact`).`communicationChannel`) satisfies (((`communicationChannel`.`communicationChannelCode`) = \"EMAIL\") and ((`communicationChannel`.`communicationValue`) = null)) end)) and ((`order`.`orderTypeCode`) = \"220\")) and ((not ((`order`.`orderCategory`) = \"EXCLUDED_CAT\")) or ((`order`.`orderCategory`) is not valued))) and ((`order`.`creationDateTime`) in (select raw max((`O2`.`creationDateTime`)) from `order` as `O2` where ((((((lower((((`O2`.`buyer`).`contact`).`firstName`)) like \"%aziz%\") or (lower((((`O2`.`buyer`).`contact`).`lastName`)) like \"%aziz%\")) or any `communicationChannel` in (((`O2`.`buyer`).`contact`).`communicationChannel`) satisfies (((`communicationChannel`.`communicationChannelCode`) = \"EMAIL\") and ((`communicationChannel`.`communicationValue`) = null)) end) and any `communicationChannel` in (((`O2`.`buyer`).`contact`).`communicationChannel`) satisfies (((`communicationChannel`.`communicationChannelCode`) = \"EMAIL\") and ((`communicationChannel`.`communicationValue`) is not null)) end) and ((`O2`.`orderTypeCode`) = \"220\")) and ((not ((`O2`.`orderCategory`) = \"EXCLUDED_CAT\")) or ((`O2`.`orderCategory`) is not valued))) group by array (`item`.`communicationValue`) for `item` in (((`O2`.`buyer`).`contact`).`communicationChannel`) when ((`item`.`communicationChannelCode`) = \"EMAIL\") end)))"
},
{
"#operator": "InitialGroup",
"aggregates": [
"count(*)"
],
"group_keys": []
}
]
}
},
{
"#operator": "IntermediateGroup",
"aggregates": [
"count(*)"
],
"group_keys": []
},
{
"#operator": "FinalGroup",
"aggregates": [
"count(*)"
],
"group_keys": []
},
{
"#operator": "Parallel",
"~child": {
"#operator": "Sequence",
"~children": [
{
"#operator": "InitialProject",
"result_terms": [
{
"as": "count",
"expr": "count(*)"
}
]
},
{
"#operator": "FinalProject"
}
]
}
}
]
},
"text": "SELECT COUNT(*) AS count FROM `order` \nWHERE `_class` = \"com.lbk.entities.OrderEntity\" \nAND ( \nLOWER(buyer.contact.firstName) LIKE '%aziz%' OR LOWER(buyer.contact.lastName) LIKE '%aziz%' \nOR ANY communicationChannel IN buyer.contact.communicationChannel SATISFIES ( communicationChannel.communicationChannelCode = 'EMAIL' AND communicationChannel.communicationValue = null ) END ) \nAND orderTypeCode = '220' \nAND (orderCategory != 'EXCLUDED_CAT' OR orderCategory is not valued ) \nAND creationDateTime in (select RAW max(O2.creationDateTime) \nfrom `order` O2 WHERE ( LOWER(O2.buyer.contact.firstName) \nLIKE '%aziz%' OR LOWER(O2.buyer.contact.lastName) LIKE '%aziz%' \nOR ANY communicationChannel IN O2.buyer.contact.communicationChannel SATISFIES ( communicationChannel.communicationChannelCode = 'EMAIL' AND communicationChannel.communicationValue = null ) END ) \nAND ANY communicationChannel IN O2.buyer.contact.communicationChannel SATISFIES ( communicationChannel.communicationChannelCode = 'EMAIL' AND communicationChannel.communicationValue is not null ) END \nAND O2.orderTypeCode = '220' \nAND (O2.orderCategory != 'EXCLUDED_CAT'\nOR O2.orderCategory is not valued) \ngroup by ( ARRAY item.communicationValue FOR item IN O2.buyer.contact.communicationChannel WHEN item.communicationChannelCode = 'EMAIL' END ))"
}
当这个查询在查询监视器中执行时,它需要(2 秒,即使我有少量文档 ~2000):
经过:1.93 秒 |执行时间:11.93s |计数:1 |尺寸:34
当使用 spring 数据从我的 spring boot 应用程序执行时,需要双倍时间(4 秒)。
感谢您的帮助
【问题讨论】:
-
这里有错字吗?您在子查询之外使用 o2。
-
你好 Johan,不,这只是格式化程序 :(,你的问题的坦克
-
这个查询及其优化可能非常复杂,以至于没有一个简单的答案。我建议你把它带到 Couchbase N1QL 论坛,它对扩展讨论有更好的支持。 forums.couchbase.com/c/n1ql/l/latest
-
使用 USE INDEX (idx_customer1) 避免 intersectScan。你在子查询中缺少
_class= "com.lbk.entities.OrderEntity" 吗? communicationchannel.communicationvalue = NULL 始终为假。 NULL 不能与关系运算符比较,需要使用 IS NULL。推荐通过blog.couchbase.com/n1ql-practical-guide-second-edition -
谢谢你们,最后我想我应该阅读本指南。
标签: couchbase n1ql spring-data-couchbase