時間ベースの条件で結合やフィルタリングを行う場合は、パラメータを文字列として渡すのではなく、リテラルを使用することをお勧めします。これにより、ソース・システムはこれらのパラメータを変換する必要がなくなります。
例
Date |
|
Time |
|
Timestamp |
|
詳しくはLiteralsをご覧ください。
この例では、単純な日付比較がパフォーマンスに悪影響を与えるシナリオを見ていきます:
SELECT "SalesOrderID" ,"OrderDate"FROM "mssql_advworks_2019.AdventureWorks2019.Sales.SalesOrderHeader"WHERE OrderDate >= '2011-05-31' or OrderDate >= {d '2011-05-31' } LIMIT 500;;クエリプランを調べると、元のクエリがどのように変換され、データソースにプッシュダウンされたかがわかります:
OrderDate >= '2011-05-31'は と訳されました;(convert(g_0.OrderDate, string) >= '2011-05-31')OrderDate >= {d '2011-05-31' }は に翻訳されました。(g_0.OrderDate >= {ts'2011-05-31 00:00:00.0'})
MSSQL Server Profilerを使用することで、さらに多くの洞察を得ることができます。これはMSSQLが受信した実際のクエリです:
SELECT TOP 500 g_0."SalesOrderID" AS "c_0", g_0."OrderDate" AS "c_1" FROM "AdventureWorks2019"."Sales"."SalesOrderHeader" g_0 WHERE (convert(varchar(34), g_0."OrderDate", 21) >= N'2011-05-31' COLLATE Latin1_General_CS_AS) OR g_0."OrderDate" >= CAST('2011-05-31 00:00:00.0' AS DATETIME2)'WHERE句のこの部分は非常に効率的です、g_0."OrderDate" >= CAST('2011-05-31 00:00:00.0' AS DATETIME2)'。文字列は一度日付時刻の値に変換され、その後カラムと比較されます。もし "OrderDate "カラムにインデックスがあれば、この比較はインデックスを利用することができます。
(convert(varchar(34), g_0."OrderDate", 21) >= N'2011-05-31' COLLATE Latin1_General_CS_AS)は非効率で遅い。テーブルのすべての行は、バイナリ保存形式から人間が読める文字列に変換され、日付文字列と比較されなければなりません。日付から文字列への変換は、OrderDateのインデックスが無視されることも意味します。この変換はパフォーマンスを著しく低下させるので、避けるべきです。
