2017-05-24 21 views
1

差別大查詢

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過濾器也不會過濾,因爲所有數據都是xxxyyy

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_的結構鏈接表:

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

createdOn場表示從1970年蜱日期值,並且是自2000年01一月到今天,日期隨機。

amount字段是從10到10,000的隨機貨幣值(小數點後兩位)。

number字段是自動編號字段。

我有兩個非常相似的(在我看來)查詢,一種方式(發票工作)非常,非常快速地工作,另一個需要很長時間。

此查詢需要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 

我認識到這兩個查詢正在提供不同的數據,但處理時間應該是相同的當不可它呢?他們都通過鏈接表格過濾兩個表格,並在另一個表格上執行聚合。我不明白爲什麼一種方式比另一種方式快得多。請問我能做些什麼來提高這些查詢的性能?

+0

在'data_jobs'中,您同時具有兩個屬性的過濾條件:'tenantId'和'createdOn'。如果你在兩者上都創建了一個持久索引,那麼你的查詢的性能如何,因此將其定義爲'tenantId,createdOn'。多屬性索引可以真正幫助,特別是當您在同一個查詢中使用這兩個索引時。 –

+0

謝謝@DavidThomas我會放棄這項工作,但正如我所說的那樣,這些過濾器實際上並沒有帶走任何記錄(故意 - 我是最壞情況下的測試),並且他們可能會加快查詢,讓他們成爲單指數,我懷疑它會很多 - 但我一定會放棄它。 – Anupheaus

+0

發表您對此內容的評論。隨着調整我有一個查詢,需要124秒下降到0.2秒。他們的關鍵是多列索引並構建查詢,以便AQL引擎可以輕鬆確定要使用的索引。 –

回答

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,它仍然似乎沒有使用索引?)

任何人都可以解釋這個嗎?