概要
AutoTuneは、アプリケーションのプロファイリングに基づいてORMクエリを自動的にチューニングできるEbeanの機能です。プロファイリングは、アプリケーションによって使用されるオブジェクトグラフのどの部分を特定し、ORMクエリのselect()
およびfetch()
部分をチューニングするために使用できる最適化されたクエリを提供します。
起点
ORMクエリには、wpbnw.BQejAt.Bzpaqe
のようなハッシュキーを持つ起点
があります。これは、クエリのビーン型とクエリ型、クエリを実行する直近のメソッド、およびコールスタックの3つの部分で構成されています。
起点ハッシュにはコールスタックが含まれているため、単一のクエリを異なるユースケースに合わせてチューニングできます。たとえば、IDによる顧客検索クエリは、3つの異なるコールスタックによって呼び出すことができ、各ケースに合わせてチューニングできます。1つは顧客名のみをフェッチし、2つ目のユースケースはいくつかの顧客詳細をフェッチし、3つ目のユースケースは顧客の配送先住所と請求先住所と一緒に顧客の詳細をフェッチするかもしれません。
このように、AutoTuneは、手動による明示的なクエリチューニングでは簡単にはできない、複数のユースケースに対して単一のクエリをチューニングできます。
プロファイリング
プロファイリングがオンになっている場合、オブジェクトグラフの使用状況
(アプリケーションによって使用されるパス/プロパティ)を収集し、オブジェクトグラフの使用状況を起点
に関連付けます。使用されるパス/プロパティをマージすると、効果的にselectおよびfetch句となる、チューニングされたクエリが提供されます。
プロファイリング設定はAutoTuneConfig
によって構成されますが、デフォルト設定はほとんどの場合に適していると予想され、通常はデフォルト設定でプロファイリングをオンにするだけで済みます。
- profilingBase = 5 : これは、起点の最初の5つのクエリがプロファイリングされることを意味します
- profilingRate = 0.01 : 起点の最初の5つのクエリの後、クエリの1%がプロファイリングされます
- garbageCollectionWait = 100 : シャットダウン時にGCをトリガーし、プロファイリング情報を収集するために100ミリ秒待機します
- skipCollectionOnShutdown = false : シャットダウン時にGCと待機をスキップする場合は、これをtrueに設定します
- profilingFile = "ebean-profiling" : これは、プロファイリング出力のファイル名です
プロファイリングをオンにする
ebean.autotune.profiling=true
ServerConfig serverConfig = ...
// turn on profiling
serverConfig.getAutoTuneConfig().setProfiling(true);
プロファイリングファイル: ebean-profiling.xml
プロファイリングがオンになっている場合、シャットダウン時に収集されたプロファイリングがプロファイリングファイルに出力されます。プロファイリングファイルには、次の3つのセクションが含まれています
profileNew
: 以前の自動チューニングエントリがない新しいプロファイリングエントリprofileDiff
: プロファイリングクエリが既存の自動チューニングエントリと異なるエントリprofileEmpty
: プロファイリングが収集されなかった既存の自動チューニングエントリの起点キー
profileNew
通常、profileNew
エントリをプロファイリングから自動チューニングファイルに転送できます。これらは、新しいコード/クエリによるもの、または起点ハッシュコードが変更されたために発生した新しいエントリを表します。
profileDiff
これらのエントリは、プロファイリングクエリを既存のチューニングクエリと比較したときに違いがあることを示します。たとえば、追加のパス/プロパティが現在使用されるようになったコード変更などです。
profileDiffエントリの場合、detail
にはプロファイリングによって提案されたクエリが含まれており、original
には既存のチューニングされたクエリが含まれています。
例
以下の例では、diffエントリは、この起点に対して、アプリケーションがorder.shipDateとcustomer.nameも追加で使用していることを示しています。
<profileDiff>
<origin key="h_zOh.wpbnw.DJ7cI3" beanType="org.example.domain.Order"
detail="select (shipDate,orderDate) fetch customer (id,name) "
original="select (orderDate) fetch customer (id) ">
<callStack>org.example.domain.finder.OrderFinder.byStatus(OrderFinder.java:38)
org.example.domain.finder.OrderFinderTest.testOther(OrderFinderTest.java:51)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
</callStack>
</origin>
</profileDiff>
profileEmpty
profileEmpty
エントリは、プロファイリングが収集されなかったチューニング起点です。関連するアプリケーションの部分が実行されなかった場合、またはコードが変更/削除されたために関連するハッシュが有効でなくなった場合、プロファイル空のエントリが表示されます。
例
<profileEmpty>
<origin key="wpbnw.BQejAr.Bzpaqe"/>
<origin key="wpbnw.BQejAr.CEn3iT"/>
</profileEmpty>
チューニング
チューニングがオンになっている場合、Ebeanの起動時にチューニングファイルが読み取られ、チューニングクエリとその関連する起点キーがロードされます。
チューニング可能なORMクエリは、その起点キーを取得し、関連するチューニングクエリを検索します。起点キーに一致するチューニングクエリがある場合、クエリチューニングがクエリに適用されます。
select() / fetch()
このクエリチューニングは、チューニングクエリからのselect/fetch句をクエリに効果的に適用します。クエリにチューニングクエリにないfetch句が既にいくつかある場合、これらは現在削除されません。
JPA FetchGroups
JPA/JDO FetchGroupsに精通している場合は、このクエリチューニングをFetchGroupの適用とほぼ同じと見なすことができます。ただし、EbeanはSQLデカルト積を生成せず、常にfirstRows/maxRowsを尊重し、最大深度制限(maxDepthなし)がないことに注意する必要があります。Ebeanのselect/fetchは完璧であり、隠れた制限/落とし穴/落とし穴はありません。
チューニングをオンにする
ebean.autotune.queryTuning=true
# optionally specify the location of ebean-autotune.xml
#ebean.autotune.queryTuningFile=ebean-autotune.xml
ServerConfig serverConfig = ...
AutoTuneConfig autoTuneConfig = serverConfig.getAutoTuneConfig();
// turn on query tuning
autoTuneConfig.setQueryTuning(true);
// Optional: specify full path to ebean-autotune.xml
// autoTuneConfig.setQueryTuningFile(" ...some file path... ");
チューニングファイル: ebean-autotune.xml
ebean-autotune.xmlチューニングファイルには、起点とチューニングクエリのリストが含まれています。
例
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<autotune xmlns="http://ebean-orm.github.io/xml/ns/autotune">
<origin key="wpbnw.BQejAr.Bzpaqe" beanType="org.example.domain.Order"
detail="select (orderDate,shipDate,status) fetch details (id,orderQty)"
original="select ">
<callStack>org.example.domain.finder.OrderFinder.byStatus(OrderFinder.java:38)
org.example.domain.finder.OrderFinderTest.test(OrderFinderTest.java:20)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
</callStack>
</origin>
<origin key="wpbnw.BQejAr.CEn3iT" beanType="org.example.domain.Order"
detail="select (orderDate,shipDate) fetch customer (id,name) "
original="select ">
<callStack>org.example.domain.finder.OrderFinder.byStatus(OrderFinder.java:38)
org.example.domain.finder.OrderFinderTest.testOther(OrderFinderTest.java:51)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
</callStack>
</origin>
</autotune>
ebean-autotune.xmlへのデータの投入
現時点では、プロファイリングファイルからコピーアンドペーストして手動でebean-autotune.xmlにデータを投入しますが、シャットダウン時にプロファイリングをチューニングファイルにマージするオプションが検討されます。