Большая разница во времени, необходимом для выполнения графовых запросов

На основании следующих коллекций:

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 или же yyy,

Общая структура data_jobs и data_invoices:

tenantId: string;
createdOn: number;
data: [{
    createdOn: number;
    values: {
        ...collection specific data here...
    };
}];

Структура сбора данных для data_invoices является:

number: number;
amount: number;

Структура сбора данных для data_jobs является:

name: string;

Структура таблицы data_links:

createdOn: number;
replacedOn?: number; // though I don't have any records with this value set

createdOn поле - это значение даты, представленное в виде галочек с 1970 года, и случайная дата с 01 января 2000 года по сегодняшний день.

amount Поле представляет собой случайное значение валюты (2 десятичных знака) от 10 до 10000.

number field это поле типа автонумерации

У меня есть два очень похожих (на мой взгляд) запроса: один способ (задания на счета) работает очень и очень быстро, другой - на возраст.

Этот запрос занимает 1,85 секунды:

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

Этот запрос занимает 8,5 секунд:

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]
    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
    SORT invoiceData.values.amount ASC
    LIMIT 0,8
    RETURN invoice

Я понимаю, что оба запроса предоставляют разные данные, но время обработки должно быть одинаковым, не так ли? Они оба фильтруют обе таблицы через таблицу связей и выполняют агрегирование с другой. Я не понимаю, почему один путь намного быстрее, чем другой. Могу ли я что-нибудь сделать, чтобы повысить производительность этих запросов, пожалуйста?

1 ответ

Хорошо, странно, но я наткнулся на очень нелогичное (по крайней мере для меня) решение. Сортировка сначала, затем фильтр...???

Этот запрос теперь занимает 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 и он все еще не использует индекс?)

Кто-нибудь может объяснить это, пожалуйста?

Другие вопросы по тегам