SELECT [BusinessEntityID],[NationalIDNumber],[LoginID],[OrganizationNode]
FROM [AdventureWorks2014].[HumanResources].[Employee]
where BusinessEntityID = 5
実際の実行プランでクエリを実行した後、SQL Serverによってconvert_implicit()関数が呼び出されます。
SELECT [BusinessEntityID],[NationalIDNumber],[LoginID],[OrganizationNode]
FROM [AdventureWorks2014].[HumanResources].[Employee]
where BusinessEntityID = convert(int,5)
明らかに、スカラー値を明示的に整数型に変換すると、convert_implicit()関数が呼び出されません。明示的な変換を使用せずにスカラーint値の暗黙的な変換を回避できる方法はありますか?また、暗黙的な変換、明示的な変換、および変換がまったく発生しなかった場合のパフォーマンスの違いを知りたいです。
整数列の暗黙的な変換を回避する方法
列ではなく、暗黙的に変換されたパラメーターです。
クエリはSQL Serverによって Simple Parameterization の影響を受けます。このプロセスで使用されるデータ型を制御することはできません。リテラル値を保持できる最小のデータ型を使用します(5
はtinyint
に適合します)。 tinyint
パラメータをint
に暗黙的にキャストしても問題は発生しません。
ただし、int
、smallint
、tinyint
のキャッシュに複数のプランが存在しないようにし、暗黙のキャストを取り除くには、クエリを自動的にパラメーター化するのではなく、データ型int
のパラメーターを使用してクエリを明示的にパラメーター化できます。
EXEC sys.sp_executesql
N'SELECT [BusinessEntityID],[NationalIDNumber],[LoginID],[OrganizationNode]
FROM [AdventureWorks2014].[HumanResources].[Employee]
where BusinessEntityID = @BusinessEntityID',
N'@BusinessEntityID INT',
@BusinessEntityID = 5;
もう1つの方法は、以下のように冗長なAND 1=1
を追加して、単純なパラメーター化をブロックすることです。ただし、これはお勧めしません。渡したリテラル値ごとにプランがコンパイルおよびキャッシュされるためです。
SELECT [BusinessEntityID],
[NationalIDNumber],
[LoginID],
[OrganizationNode]
FROM [AdventureWorks2014].[HumanResources].[Employee]
where BusinessEntityID = 5
AND 1=1
変数を使用すると、クエリの再利用のメリットも得られます
Declare @ BeID int = 5
select xxx where BuisnessEntityID = @BeID
確実にしたい場合は、変数を使用するかcast/convert
を使用して、クエリを強く入力する必要があります。
select xxx where BuisnessEntityID = CAST (5 as int)
暗黙的な変換のパフォーマンスオーバーヘッドは無視できると思いますが、間違っているかもしれません。ただし、変数を使用すると、クエリキャッシュを再利用できるというメリットが確実に得られます。