【问题标题】:Slow n1ql query using object of objects structure使用对象结构的对象的慢 n1ql 查询
【发布时间】:2017-10-12 14:17:06
【问题描述】:

在我们的 couchbase 数据库中,我们有一个包含相对较大对象的存储桶。这些对象内部还有其他对象,比如说人。这应该是一个数组,但是由于某种原因,我们不得不将它创建为对象的对象,这就是它的样子:

{
    "companyName": "company name",
    "companyid": "11111-GUID-11111",
    "people": {
        "22222-GUID-22222": {
            "peopleid": "22222-GUID-22222",
            "name": "name1"
        },
        "33333-GUID-33333": {
            "peopleid": "33333-GUID-33333",
            "name": "name2"
        },
        "44444-GUID-44444": {
            "peopleid": "44444-GUID-44444",
            "name": "name3"
        }
    }
}

它也有类似结构的子对象。

我可以像这样对该文档进行查询:

SELECT c.*
FROM companies c
WHERE ANY v IN OBJECT_VALUES(c.people) SATISFIES v.peopleid = "22222-GUID-22222" END 
LIMIT 100 
OFFSET 40000;

我有一个包含 50000 个这样的文档的存储桶。

上面的查询运行完美,并给出了正确的响应,但我必须等待大约 25 秒才能得到响应。

有没有可能在这个结构上创建适当的索引?或者任何可以加快查询速度的解决方案?

【问题讨论】:

    标签: node.js couchbase n1ql


    【解决方案1】:

    您可以尝试按照https://developer.couchbase.com/documentation/server/current/n1ql/n1ql-language-reference/indexing-arrays.html 的描述创建数组索引。您提到大对象检查数组索引键大小限制。

    在公司上创建索引 ia1 (DISTINCT ARRAY v.peopleid FOR v IN OBJECT_VALUES(people) END);

    当您使用大偏移量时,您会丢弃大量文档。如果您使用的是 4.6.2+(因为它可以使用上面链接中描述的隐式覆盖数组索引)您可以使用覆盖查询获取 LIMIT 文档的 META().id 并获取如下所需的文档。

    SELECT c.* FROM
        (SELECT RAW META(c).id FROM companies c
           WHERE ANY v IN OBJECT_VALUES(c.people) 
                      SATISFIES v.peopleid = "22222-GUID-22222" END 
           LIMIT 100 OFFSET 40000) AS q 
     JOIN companies c ON KEYS q ;
    

    【讨论】:

    • 您可以创建另一个索引并在该 CREATE 索引 ia2 ON 公司上进行查询 (DISTINCT ARRAY v.petid FOR v IN OBJECT_VALUES(pets) END);
    • 请查看示例 4:索引嵌套数组 (C4,Q4) 的各个元素,因为 OBJECT_VALUES() 生成数组并遵循类似developer.couchbase.com/documentation/server/current/n1ql/…
    • 您是否尝试了两个 ANY 子句,一个用于 peopleid,另一个用于两个索引的 petid
    • 对于 companyid,您可以创建复合索引,如 CREATE index ia1 ON Companies (DISTINCT ARRAY v.peopleid FOR v IN OBJECT_VALUES(people) END, companyid);并放弃 ia3。这很棘手,因为您在满足条件上有两个条件,并且索引不会覆盖用户(索引没有两个信息),最好的方法是保留 ia1 和 SELECT c.* FROM Companies c WHERE ANY v IN OBJECT_VALUES(c.people ) 满足 OBJECT_VALUES(v.pets) 中的任何宠物满足 pet.petid = "1111111-111111-pet" END AND v.peopleid = "1111111-111111-people" END AND c.companyid != "000045001-company" 限制 30偏移量 40000;
    • 也试试这个。 CREATE index ia4 ON Companies (DISTINCT ARRAY (DISTINCT ARRAY [v.peopleid,p.petid] FOR p IN OBJECT_VALUES(v.pets) END) FOR v IN OBJECT_VALUES(people) END, companyid); SELECT c.* FROM (SELECT RAW META(c).id FROM Companies c WHERE ANY v IN OBJECT_VALUES(c.people) 满足任何 p in OBJECT_VALUES(v.pets) 满足 [v.peopleid, p.petid] = [" 1111111-111111-people","1111111-111111-pet"] END END AND c.companyid != "000045001-company" LIMIT 30 OFFSET 40000) AS q JOIN Companies r ON KEYS q;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多