2017-05-24 7 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 

リンク集は、ランダムなジョブに1枚の請求書を接続するので、ジョブは、ゼロ以上の請求書を持っていることがあります。請求書には1つ以上のジョブが必要ですが、私のデータでは、各請求書は1つのジョブにのみ対応しています。 dateフィルタは、すべてのデータがxxxまたはyyyのいずれかであるため、フィルタに実際にデータをフィルタ処理することはなく(指定された日付の値よりも小さい)、tenantIdフィルタもフィルタしません。

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年1月1日からのランダムな日付であるとして表される日付値です。

amountフィールドは、10〜10,000の任意の通貨値(小数点以下2桁)です。

numberフィールドは、自動番号型フィールドです。

2つの非常によく似た質問がありますが、1つの方法(請求書へのジョブ)は非常に早く、もう1つは時間がかかります。

このクエリは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 

「私は両方のクエリが異なるデータを提供していることを認識しますが、処理時間は同じshouldnする必要がありますそれ?両方とも、リンクテーブルを介して両方のテーブルをフィルタリングしており、両方とも他方のテーブルで集約を実行しています。なぜ片方向が他の方法よりもずっと速いのか分かりません。これらのクエリのパフォーマンスを向上させるためにできることはありますか?

+0

'data_jobs'には、同時に2つの属性、つまりtenantIdと' createdOn'のフィルタ条件があります。両方に永続インデックスを作成した場合のクエリのパフォーマンスは、 'tenantId、createdOn'と定義してください。複数の属性インデックスは、特に同じクエリで両方を使用している場合に特に役立ちます。 –

+0

@DavidThomasありがとうございました。しかし、私が言ったように、それらのフィルタは実際にレコードを取ることはありません(故意に - 私は最悪のシナリオテストです)。単一のインデックス、私はそれが多くなることを疑う - 私は間違いなくそれを行っても間に合うでしょう。 – Anupheaus

+0

あなたが見つけたものにコメントを投稿してください。微調整をすると、私は124秒間で0.2秒かかったクエリを1つ持っていました。私にとって重要なのは、マルチカラムインデックスであり、クエリを作成して、AQLエンジンがどのインデックスを使用するのかを簡単に判断できるようにすることでした。 –

答えて

0

奇妙なことですが、私は非常に直観的な(少なくとも私にとっては)解決策を見つけました。最初に並べ替え、次にフィルターをかける... ???

このクエリは、現在1.4秒かかる:data[*].values.amountに永続的なインデックスを追加するにもかかわらず

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 

を、それはまだそれを使用していない(私もSORT invoice.data[0].values.amount ASCを試してみましたが、まだインデックスを使用していないようでした?)

これは誰でも説明できますか?

関連する問題