インデックスを使用しない Hibernate によって生成されたクエリに問題があります。データベースへのアクセスは JTDS を使用して Java から行われ、サーバーのバージョンは SQL Server 2005の最新のサービス パックです。
フィールドは NULL 可能であり、特定のシナリオでは完全に NULL になる可能性がある外部キーです。列はクラスター化されていないインデックスを介してインデックス付けされますが、列が完全に NULL の場合、インデックスは使用されず、多数のフル テーブル スキャンが作成されます。そしてパフォーマンスの問題。
この状況は、次の SQL コードを含む標準のクエリ アナライザーを使用して確認することもできます。
テーブルとインデックスを作成する
CREATE TABLE [dbo].[TestNulls](
[PK] [varchar](36) NOT NULL,
[DATA] [varchar](36) NULL,
[DATANULL] [varchar](36) NULL,
CONSTRAINT [PK_TestNulls] PRIMARY KEY NONCLUSTERED
(
[PK] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE NONCLUSTERED INDEX [IDX_DATA] ON [dbo].[TestNulls]
(
[DATA] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF,
IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [IDX_DATANULL] ON [dbo].[TestNulls]
(
[DATANULL] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF,
IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
newid 関数を使用して、いくつかのランダム データを入力します。
declare @i as int
set @i = 0
while (@i < 500000)
begin
set nocount on
insert into TestNulls values(NEWID(), NEWID(), null)
insert into TestNulls values(NEWID(), null, null)
insert into TestNulls values(NEWID(), null, null)
set @i = (@i + 1)
set nocount on
end;
このクエリは、フル テーブル スキャンを実行します
declare @p varchar(36)
set @p = NEWID()
select PK, DATA, DATANULL from TestNulls
where DATANULL = @p
「and DATANULL IS NOT NULL」でクエリを完了すると、クエリはインデックスを使用するようになりました。
助けが必要:
- JTDS/Hibernate の組み合わせにインデックスを使用させるにはどうすればよいですか (sendStringParametersAsUnicode はデフォルトで既に false に設定されています)。
- null 許容フィールドを使用するすべての hibernate クエリに「and column is not null」を追加する方法はありますか?
- この動作について何か説明はありますか?
よろしくマッシモ