時間ベースの条件で結合やフィルタリングを行う場合は、パラメータを文字列として渡すのではなく、リテラルを使用することをお勧めします。これにより、ソース・システムはこれらのパラメータを変換する必要がなくなります。

Date

{d 'yyyy-mm-dd'}

Time

{t 'hh-mm-ss'}

Timestamp

{ts 'yyyy-mm-dd hh:mm:ss.[fff...]'}

詳しくは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のインデックスが無視されることも意味します。この変換はパフォーマンスを著しく低下させるので、避けるべきです。