Skip to main content

 

 

 

 

Template:OutSystems/Documentation_KB/Breadcrumb_New_Layout

 

 

Template:OutSystems/OSLanguageSwitcher

 

 

 

OutSystems

インライン展開を乱用しない

OutSystems SQLクエリには、SQLコンテンツを挿入することができます。これにあたっては、インライン展開を使用します。このパラメータは、データベース内で作成されないという点でSQLパラメータとは異なります。実行時に計算され、SQL呼び出し内でテキストとして展開されるのです。

インライン展開の一般的な使用例を以下に示します。

例1:

動的な条件 - たとえば、ユーザーがUIで検索キーワードを入力した場合は「SearchClause」というインライン展開パラメータで“and {User}.[Name] like '%”+SearchKeyword+”%'”を渡し、それ以外の場合は同じパラメータで空の文字列を渡します。

SQLクエリ定義でコンテンツをテキストとして展開するには、このインラインパラメータを使用します。

SELECT {User}.[Name], {User}.[Phone]  
FROM {User}  
WHERE {User}.[IsActive]  
@SearchClause  
ORDER BY {User}.[Name]

例2:

動的な値セット - たとえば、前のクエリやアクションの結果のレコードリストをカンマ区切り値の文字列に変換し、それを「UserIds」というインライン展開でクエリに渡します。 

SELECT {User}.[Name], {User}.[Phone]  
FROM {User}  
WHERE {User}.[IsActive]  
AND {User}.[Id] in { @UserIds }  
ORDER BY {User}.[Name]

影響

これらの2つの例ではクエリの呼び出しのたびにまったく異なるテキストがインラインパラメータに渡され、データベースエンジンに対してまったく異なるクエリが生成されるおそれがあります。

インラインパラメータが頻繁に変更されると、エンジンで異なるクエリが絶えず生成されるため、データベースの実行計画を最適化することができません。これはパフォーマンスに大きく影響します。初回実行時に数秒かかるような大量のデータを含む複雑なクエリは、統計的最適化を行うことで、それ以降の呼び出しではミリ秒レベルで実行できるようになります。

ベストプラクティス

Expand Inlineパラメータを避けるための推奨事項は以下のとおりです。

  • オプションフィルタの処理に動的なSQLを使用しないようにします。代わりに、固定条件を使用してオプションに対応します。

    例1を修正するには、SearchClauseインラインパラメータの代わりにSearchKeywordを通常のパラメータとして送信し、クエリを以下のように変更します。

    SELECT {User}.[Name], {User}.[Phone]  
    FROM {User}  
    WHERE {User}.[IsActive]  
    AND @SearchKeyword = '' OR {User}.[Name] like '%'+@SearchKeyword+'%'  
    ORDER BY {User}.[Name]
    

    これにより、データベースエンジンへのクエリを常に同一にすることができます。検索キーワードがないときに実際の条件が実行されないようにするため、任意の条件(@SearchKeyword = '')を最初に配置することが重要です。データベースエンジンはこのような「ダミー」条件の最適化が非常に得意であるため、クエリをオプションフィルタ向けに処理する作業の負荷はほとんど無視できるレベルです。

  • クエリの結果をカンマ区切り値として次のクエリに挿入する代わりに、サブクエリを使用します。

    例2のUserIdsが、特定のロジックでユーザーを選択する複雑なクエリから取得されたものである場合、そのクエリを同じSQLクエリに含めることができます。これにより、パフォーマンスを低下させるおそれのあるIN条件も避けることができます。例:

    WITH UserIdTable (Id) as (SELECT ...)  
    SELECT {User}.[Name], {User}.[Phone]  
    FROM {User}  
    INNER JOIN UserIdTable on UserIdTable.ID = {User}.[ID]  
    WHERE {User}.[IsActive]  
    ORDER BY {User}.[Name]
    

クエリを固定し、データベースエンジンによって最適化されるようにしました。

  • カンマ区切り値リストが単一のクエリで取得されたものではない場合、一時テーブルを使用します。値リストが複雑なロジックの結果(SQL以外の処理)である場合、リストに要素が追加され続けることがあります。カンマ区切り値リストに要素を追加する代わりに、一時テーブルに値を追加します(SQLクエリで一時テーブルを作成する方法については、Googleで「Oracle一時テーブル」や「SQL一時テーブル」を検索してください)。一時テーブルを追加すると、例2は次のように変わります。
    SELECT {User}.[Name], {User}.[Phone]  
    FROM {User}  
    INNER JOIN TemporaryTable on TemporaryTable.ID = {User}.[ID]  
    WHERE {User}.[IsActive]  
    ORDER BY {User}.[Name]
    
  • Was this article helpful?