执行图表查询所花费的时间差异很大

时间:2017-05-24 16:54:25

标签: arangodb aql

基于以下集合:

data_invoices (document, 100,000 total records, 2 tenants)
    hash: tenantId
    persistent: createdOn

data_jobs (document, 10,000 total records, 2 tenants)
    hash: tenantId
    persistent: createdOn

data_links (edge, 100,000 total records)
    persistent: createdOn
    persistent (sparse): replacedOn

链接集合会将一张发票连接到随机作业,因此作业可能包含零个或多个发票。发票应包含一个或多个作业,但在我的数据中,每个发票仅与一个作业匹配。 date过滤器实际上并不过滤掉任何数据(它们都小于指定的日期值),tenantId过滤器也没有过滤掉,因为所有数据都是xxx或{{1 }}

data_jobs和data_invoices的通用结构是:

yyy

tenantId: string; createdOn: number; data: [{ createdOn: number; values: { ...collection specific data here... }; }]; 的集合特定数据结构是:

data_invoices

number: number; amount: number; 的集合特定数据结构是:

data_jobs

data_links表的结构是:

name: string;

createdOn: number; replacedOn?: number; // though I don't have any records with this value set 字段是日期值,表示为1970年的刻度,是从2000年1月1日到今天的随机日期。

createdOn字段是从10到10,000的随机货币值(小数点后两位)。

amount字段是自动编号字段。

我有两个非常相似(在我看来)的查询,一种方式(工作到发票)工作非常非常快,另一种方式需要很长时间。

此查询需要1.85秒:

number

此查询需要8.5秒:

LET date = 1495616898128

FOR job IN data_jobs
    FILTER job.tenantId IN ['xxx', 'yyy']
    FILTER job.createdOn<=date
    LET jobData = (job.data[* FILTER CURRENT.createdOn<=date LIMIT 1])[0]
    FILTER CONTAINS(jobData.values.name, 'a')
    LET invoices = (
        FOR invoice, link IN 1 INBOUND job data_links
            FILTER link.createdOn<=date AND (link.replacedOn == NULL OR
                link.replacedOn>date)
            LET invoiceData = (invoice.data[* FILTER CURRENT.createdOn<=date LIMIT 1])[0]
            FILTER invoiceData.values.amount>1000
            COLLECT WITH COUNT INTO count
            RETURN {
                count 
            }
    )[0]
    FILTER invoices.count>0
    SORT jobData.values.name ASC
    LIMIT 0,8
    RETURN job

我意识到两个查询都提供不同的数据,但处理时间应该是相同的吗?它们都通过链接表过滤两个表,并在另一个表上执行聚合。我不明白为什么一种方式比另一种方式快得多。我有什么办法可以提高这些查询的性能吗?

1 个答案:

答案 0 :(得分:0)

好的,很奇怪,但我偶然发现了一个非常反直觉(至少对我而言)的解决方案。先排序,然后过滤...... ???

此查询现在需要1.4秒:

LET date = 1495616898128

FOR invoice IN data_invoices
    FILTER invoice.tenantId IN ['xxx', 'yyy']
    FILTER invoice.createdOn<=date
    LET invoiceData = (invoice.data[* FILTER CURRENT.createdOn<=date LIMIT 1])[0]
    SORT invoiceData.values.amount ASC
    FILTER invoiceData.values.amount>1000
    LET jobs = (
        FOR job, link IN 1 OUTBOUND invoice data_links
            FILTER link.createdOn<=date AND (link.replacedOn == NULL 
                OR link.replacedOn>date)
            LET jobData = (job.data[* FILTER CURRENT.createdOn<=date LIMIT 1])[0]
            FILTER CONTAINS(jobData.values.name, 'a')
            COLLECT WITH COUNT INTO count
            RETURN {
                count 
            } 
    )[0]
    FILTER jobs.count>0        
    LIMIT 0,8
    RETURN invoice

尽管在data[*].values.amount上添加了持久索引,但它仍然没有使用它(我甚至试过SORT invoice.data[0].values.amount ASC但它似乎仍然没有使用索引?)

有人可以解释一下吗?