AQL 最適化の推奨事項

このページの内容

お困りですか?

アトラシアン コミュニティをご利用ください。

コミュニティに質問

このページでは、Jira Service Management で高度なクエリ言語 (AQL) によるクエリを実行する方法と、AQL クエリを最適化するためのヒントについて説明します。このページの説明では、例としてオブジェクト スキーマが 3 つあるとしましょう。

objectSchema含む
  • 100 のオブジェクト タイプがあります。そのうちの 1 つには Employees という名前が付いていて、10,000 個のオブジェクトが含まれています
  • 合計で 1,000,000 個のオブジェクトがあります 

このスキーマは、次のような Jira プロジェクトに接続されています。

  • ToDo」、「進行中」、「完了」というステータスの Jira 課題が 1,000,000 個含まれる
  • 既定で、アセット カスタム フィールド (関連アセット) に接続されている

このスキーマの 200,000 個のオブジェクトは、上記の Jira プロジェクトの 200,00 個の Jira 課題に接続されています。

  • CPUMemoryOfficeServerRegion という名前の 5 個のオブジェクト タイプがあり、各オブジェクト タイプには、約 10 個のオブジェクトが含まれています
  • 合計で 50 個のオブジェクトがあります

このスキーマは、次のような Jira プロジェクトに接続されています。

  • ToDo進行中完了」というステータスの Jira 課題が 50 個含まれる
  • 既定で、アセット カスタム フィールド (関連アセット) に接続されている

このスキーマの 10 個のオブジェクトは、上記の Jira プロジェクトの 10 個の Jira 課題に接続されています。

AQL クエリの実行方法

AQL クエリは、次の 3 つのフェーズで実行されます。

  1. スコーピング:このフェーズでは、クエリに一致しない大量のデータをスコープ アウトすることで、非常に簡単に決定できる句に基づいて潜在的な結果候補が返されます。
    基本的な句の例としては、objectSchemaobjectSchemaIdobjectTypeobjectTypeIdIdKey などがあります。
  2. 述語:このフェーズでは、AQL クエリから関数 (述語) を生成します。これをオブジェクトに対して実行し、テスト フェーズで結果が有効であるかどうかを決定します。クエリにインバウンドまたはアウトバウンドの参照、または接続チケットが含まれている場合、特にインバウンドまたはアウトバウンドの参照にネストされた AQL クエリが含まれ、接続チケットにネストされた JQL クエリが含まれている場合、このフェーズはより複雑になります。
    いくつかのクエリがどのように変換されるかを見てみましょう。
    例 1:
    クエリ:

    objectSchema = SMALL AND Name == "Sydney Office"

    は次の擬似コードに変換されます。

    return (object.objectSchema.name == "SMALL" && object.name == "Sydney Office")

    例 2:
    クエリ:

    object NOT HAVING connectedTickets() OR object NOT HAVING outboundReferences()

    は次の擬似コードに変換されます。

    return (!connectedTicketsIndex.contains(object.id) || object.outboundReferences().isEmpty())

    例 3:
    クエリ:

    (objectSchema = SMALL OR objectType = Employees) AND Label LIKE "John" AND (object HAVING connectedTickets() OR object HAVING inboundReferences())

    は次の擬似コードに変換されます。

    return (object.objectSchema.name == "SMALL" || object.objectType.name == "Employees") && object.label.contains("John") && (connectedTicketsIndex.contains(object.id) || object.inboundReferences.isNotEmpty())
  3. テスト:スコーピング フェーズで決定されたすべてのオブジェクトを、述語フェーズで生成された式に対して実行し、実際の結果を返します。
    上の例 1 では、クエリの範囲はオブジェクト スキーマ SMALL のオブジェクト ID (例:ID 1,000,001 から 1,000,050) に限定されており、以下のロジックを使用して個別にテストされます。

    return (object.objectSchema.name == "SMALL" && object.name == "Sydney Office")

    ページネーションの制限を設定した場合、このステップは希望する結果数に達するまで実行されます。
    上の例 3 では、クエリの範囲は、オブジェクト スキーマ SMALL のオブジェクト タイプ (例:ID 1,000,001 から 1,000,050) とオブジェクト スキーマ LARGE のオブジェクト タイプ Employees (例:10,000 から 20,000) であり、希望する結果数に達するまで、以下のロジックを使用して個別にテストされます。

    return (object.objectSchema.name == "SMALL" || object.objectType.name == "Employees") && object.label.contains("John") && (connectedTicketsIndex.contains(object.id) || object.inboundReferences.isNotEmpty())

AQL クエリを最適化するためのヒント

クエリの範囲を制限する

基本的な句 (オブジェクト タイプや ID など) を含めることで一度に多くのオブジェクトを除外し、クエリの範囲を制限して、結果をより速く読み込むことができます。

例 1
「John」という名前の従業員をすべて検索するには、次のクエリを実行します。

Label LIKE "John"

上記のクエリは、(オブジェクト スキーマ LARGE からの) 100 万個のオブジェクトに対してテストを行います。ただし、処理時間を大幅に節約するために、次のクエリを使用できます (代わりに、AQL は長くなります)。これは、検索対象が Employees であることがわかっているので、テスト対象のオブジェクトの数を減らせるからです (一致候補は約 10,000 件になります)。

objectType = Employees AND Label LIKE "John"

句の順序は関係ないことに注意してください。次のクエリを使用することもできます。

Label LIKE "John" AND objectType = Employees


例 2
オブジェクト スキーマ SMALL に範囲を設定した次のクエリを使用して 50 件のオブジェクトに対してテストを実行する代わりに、

objectSchema = SMALL AND Name == "Sydney Office"

オブジェクト タイプまたはオブジェクト キーのリストを指定して、範囲を狭めることができます (10 件のオブジェクトに対してテストを実行します)。

objectSchema = SMALL AND objectType = Office AND Name == "Sydney Office"

上記のクエリの述語は以下のようになります (10 件のオブジェクトに対して名前の一致がテストされます)。

return object.objectSchema = "SMALL" && object.objectType == "Office" && object.name == "Sydney Office"

例 3
inboundReferences()outboundReferences()connectedTickets() 関数を含む AQL テストは、AQL または JQL のパラメータが含まれていると計算負荷が高くなります。 

次のクエリの述語は単純で、このクエリを AQL 検索またはオブジェクト スキーマ ページで実行すると、オブジェクト スキーマが既定で選択されます。

object NOT HAVING connectedTickets() OR object NOT HAVING outboundReferences()

AND 句を使用して、connectedTickets() 関数と他の AQL 句を組み合わせる

connectedTickets() 関数は 2 つの方法で実行できます。

  • JQLなしで:object HAVING/NOT HAVING connectedTickets()
  • JQL と共に:object HAVING/NOT HAVING connectedTickets(JQL)

アセットは、アセットのカスタム フィールド割り当てをすべてインデックス化します。Jira 課題とアセット オブジェクト間のすべてのリンクはメモリに保存されます。メモリに保存されないものは、アセット オブジェクトの詳細や、特に Jira 課題です。したがって、上記の 2 つの方法では、インスタンス内のすべての接続チケットを取得するのは速くなりますが、アセット オブジェクトと Jira 課題は多対多の関係のため、JQL に一致するすべての接続チケットを取得するのは遅くなります。

JQL クエリで接続チケット機能を使用するには (例:object HAVING connectedTickets(status = "In progress"))、他の AQL クエリを使用して結果をできるだけ制限してください。

AND 演算子を使用して connectedTickets() クエリと他の AQL 句を組み合わせる場合、Jira Service Management が残りの AQL を解決し、解決されたオブジェクトの接続チケットに対して JQL 検索を実行します。

例 1
次のクエリは、

objectType = Employee 
  AND Label = John 
  AND Created > startOfYear()
  AND object HAVING connectedTickets(status = "In progress")

最初に以下の AQL クエリに解決されます。これにより、オブジェクト ID のリスト [11,21,31,41] が返され、Jira 課題 ID [1001,1002,1003] にマップされます。

objectType = Employee
  AND Label = John
  AND Created > startOfYear()

次に、JQL クエリ ISSUE IN (1001,1002,1003) AND status = "In progress" が実行され、アセット オブジェクト [11,21] にマップされる Jira 課題 ID [1001,1002] が返されます。この AQL クエリのテスト フェーズは、ID が 11 または 21 のオブジェクトをチェックする前に、Employees オブジェクト タイプに範囲が設定されます。

例 2

インスタンス全体に対して実行される次の JQL クエリを使用する代わりに、

objectType = Employee 
AND 
(label = John OR object HAVING connectedTickets(user = currentUser()))

このクエリを使用して、objectType = Employee のオブジェクト ID に接続されたチケットに対してのみ JQL クエリ (status = In progress) が実行されるようにできます。

(objectType = Employee AND label = John) 
OR 
(objectType = Employee AND object HAVING connectedTickets(user = currentUser()))

上記のクエリのテスト フェーズの範囲は、objectType = Employee のみです。

例 3
AQL 句を含むクエリが connectedTickets() 句よりも深くネストされている場合でも、connectedTickets() 関数の前に解決されます。

(Name LIKE John OR Name LIKE Jane) 
AND (object NOT HAVING connectedTickets() 
  OR ( (object HAVING inR(object = Device) OR object NOT HAVING outR(object = Host)) 
    AND Name LIKE Jim 
    AND object HAVING connectedTickets(user = currentUser())))

上記の AQL は次の順序で解決されます。

  1. 次の AQL が解決されます。

    (object HAVING inR(object = Device) OR object NOT HAVING outR(object = Host)) AND Name LIKE Jim

    AQLクエリ inboundReferences() および outboundReferences() が自動的に解決されます。

    object = Device
    object = Host

    それらがオブジェクト ID [1, 2, 3, 4, 5] および [2, 3, 4, 5, 6] に解決される場合、このクエリは事実上次のようになります。

    (Id IN (1,2,3,4,5) OR Id IN [2,3,4,5,6]) AND Name LIKE Jim

    その後、このクエリは AQL クエリ (例えば、オブジェクト ID のリスト [2, 3, 4]) として解決されます。

  2. 関連するチケットの句 user = currentUser() が解決されるようになりました。

    例 1 と同様に、残りのオブジェクト ID の接続チケットをインデックスから取得します (例えば、Jira 課題 ID [2001,2002,2003] から)。

    次に、JQL issue in (2001,2002,2003) AND user = currentUser() によって [2001,2002] が返されます。

    そして、課題 ID 2001,2002 は検索結果を形成するオブジェクト ID [2,3] にマッピングされます。

  3. 残りの AQL は通常どおりに処理されます。この時点で、AQL は次のものと同等です。

    (Name LIKE John OR Name LIKE Jane) AND (object NOT HAVING connectedTickets() OR Id in (2,3))

    また、JQL が必要ないため、句 object NOT HAVING connectedTickets() は優れたパフォーマンスを発揮します。

上記の例では、connectedTickets(user = currentUser()) が他のクエリ (Name LIKE JiminR() outR() クエリなど) とバンドルされているため、関連するチケットの一部のみがチェックされます。多くの Jira 課題が取得されないため、パフォーマンスがほぼ直線的に向上し、メモリの消費量も少なくなります。

最終更新日 2023 年 8 月 8 日

この内容はお役に立ちましたか?

はい
いいえ
この記事についてのフィードバックを送信する
Powered by Confluence and Scroll Viewport.