Использование индексов по вычисляемым полям при джойне по null

KonstN
Дата: 09.10.2003 11:35:52
У товарища возникла проблема - ему нужен left join по двум полям, одно из которых NOT NULL, а другое NULL.
В обычном варианте джойн отбрасывает совпадения где одно из полей NULL (возможно я недоглядел какие-то SETы, но поэкспериментировал с разными).
В результате изысканий найдено, что лучше всего использовать индексы по вычисляемым полям.
Кому интересно, чтобы не возиться, вот скрипт

use pubs

SET ANSI_NULLS ON
SET ARITHABORT ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
SET CONCAT_NULL_YIELDS_NULL ON
SET QUOTED_IDENTIFIER ON

if object_id('b') is not null drop table b
if object_id('a') is not null drop table a
go

create table a
(
aidnotnull int not null,
aidnull int null,
aname varchar(50),
computedaidnull as isnull(aidnull, 0),
constraint pka unique (aidnotnull, aidnull)
)

create table b
(
bid int primary key,
bname varchar(50),
aidnotnull int not null,
aidnull int null,
computedaidnull as isnull(aidnull, 0),
constraint fka foreign key (aidnotnull, aidnull) references a(aidnotnull, aidnull)
)

create index ndxaforcomputed on a(aidnotnull, computedaidnull)
create index ndxbforcomputed on b(aidnotnull, computedaidnull)

go

insert into a select 1, 1, 'a without null'
insert into a select 1, NULL, 'a with null'

insert into b select 2, 'b to a without null', 1, 1
insert into b select 3, 'b to a with null', 1, NULL

update statistics a
update statistics b
go

select * from b left join a on (b.aidnotnull = a.aidnotnull and b.aidnull = a.aidnull)
select * from b left join a on (b.aidnotnull = a.aidnotnull and b.computedaidnull = a.computedaidnull)
select * from b left join a on (b.aidnotnull = a.aidnotnull and isnull(b.aidnull, 0) = isnull(a.aidnull, 0))
go

drop table b
drop table a
go


Третий запрос - это попытка проверить, не подхватит ли оптимизатор индекс по вычисляемому полю при использовании напрямую функции выч. поля.
Не подхватил (полуофф - Oracle подхватывает FBI).
Кто-нибудь знает можно ли его заставить или может есть решение вышеозначенной задачи лучше?
Glory
Дата: 09.10.2003 12:22:49
В результате изысканий найдено, что лучше всего использовать индексы по вычисляемым полям.

У меня для всех 3-х запросов используется один и тот же план выполнения. Причем индекса по вычисляемому полю в этом плане нет.

Кто-нибудь знает можно ли его заставить или может есть решение вышеозначенной задачи лучше?

select * from b left join a on (b.aidnotnull = a.aidnotnull) and (b.aidnull = a.aidnull or (b.aidnull is null and a.aidnull is null))
KonstN
Дата: 09.10.2003 13:49:51
2 Glory
Да, признаюсь, про допусловия с or (is null and is null) я забыл.
А планы всё-таки разные.
Как это можно доказать? Я не припомню, можно ли план на MSSQL вывести в текстовом виде?