varchar 列に nvarchar 渡しても convert_implicit しなくなってた

varchar と nvarchar の列持つテーブルにそれぞれ index つけて適当にデータ突っ込んで試したら、動作変わってた。

create table [Hoge] (
  [var] varchar(20) not null,
  [nvar] nvarchar(20) not null
)
create index [Hoge_var] on [Hoge] ([var])
create index [Hoge_nvar] on [Hoge] ([nvar])

;
with cte as (select 1 as cnt union all select cnt + 1 from cte where cnt < 100000)
insert into [Hoge] ([var], [nvar])
select cnt, 100000-cnt from cte option (MAXRECURSION 0)

Azure SQL DB
(Microsoft SQL Azure (RTM) - 12.0.2000.8)

declare @nvar nvarchar(20) = N'111'
declare @var varchar(20) = '111'


select * from [Hoge] where [var] = @nvar
select * from [Hoge] where [nvar] = @nvar
select * from [Hoge] where [var] = @var
select * from [Hoge] where [nvar] = @var

f:id:odashinsuke:20191006113548j:plain

一番上のプランの動作変わってんなーってとこ。
一番上は、昔は [var] 列が convert_implicit で nvarchar になってテーブルスキャンになってたけど、実行プランの xml みたら、GetRangeThroughConvert 使って範囲検索になってた。

SQL Server 2012 の環境あったから、同じクエリ試したけどやっぱ変わってた。
(Microsoft SQL Server 2012 - 11.0.5569.0 (X64))
f:id:odashinsuke:20191006115026p:plain

どのバージョンから変わったのかまでは調べてないけど、たまには色々試してみないとダメやね~。