У меня проблема с запросом, сгенерированным Hibernate, который не использует индекс. Доступ к базе данных осуществляется из Java с использованием JTDS, а версия сервера - SQL Server 2005 , последний пакет обновления.
Поле может иметь значение 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
Если я завершу запрос с "и DATANULL IS NOT NULL", запрос теперь использует индекс.
Требуется помощь:
- Как заставить комбинацию JTDS / Hibernate использовать индекс (по умолчанию sendStringParametersAsUnicode уже имеет значение false)?
- Есть ли способ добавить "и столбец не равен нулю" для всех запросов гибернации, которые используют обнуляемое поле?
- Есть объяснение этому поведению?
С уважением
Massimo