web-dev-qa-db-ja.com

整数列の暗黙的な変換を回避する方法

  SELECT [BusinessEntityID],[NationalIDNumber],[LoginID],[OrganizationNode]
  FROM [AdventureWorks2014].[HumanResources].[Employee]
  where BusinessEntityID = 5

enter image description here

実際の実行プランでクエリを実行した後、SQL Serverによってconvert_implicit()関数が呼び出されます。

  SELECT [BusinessEntityID],[NationalIDNumber],[LoginID],[OrganizationNode]
  FROM [AdventureWorks2014].[HumanResources].[Employee]
  where BusinessEntityID = convert(int,5)

enter image description here

明らかに、スカラー値を明示的に整数型に変換すると、convert_implicit()関数が呼び出されません。明示的な変換を使用せずにスカラーint値の暗黙的な変換を回避できる方法はありますか?また、暗黙的な変換、明示的な変換、および変換がまったく発生しなかった場合のパフォーマンスの違いを知りたいです。

4
mehmood shah

整数列の暗黙的な変換を回避する方法

列ではなく、暗黙的に変換されたパラメーターです。

クエリはSQL Serverによって Simple Parameterization の影響を受けます。このプロセスで使用されるデータ型を制御することはできません。リテラル値を保持できる最小のデータ型を使用します(5tinyintに適合します)。 tinyintパラメータをintに暗黙的にキャストしても問題は発生しません。

ただし、intsmallinttinyintのキャッシュに複数のプランが存在しないようにし、暗黙のキャストを取り除くには、クエリを自動的にパラメーター化するのではなく、データ型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
10
Martin Smith

コミュニティwikiの回答

変数を使用すると、クエリの再利用のメリットも得られます

Declare @ BeID int = 5
select xxx where BuisnessEntityID = @BeID

確実にしたい場合は、変数を使用するかcast/convertを使用して、クエリを強く入力する必要があります。

select xxx where BuisnessEntityID = CAST (5 as int)

暗黙的な変換のパフォーマンスオーバーヘッドは無視できると思いますが、間違っているかもしれません。ただし、変数を使用すると、クエリキャッシュを再利用できるというメリットが確実に得られます。

0
user126897