powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Сравнение СУБД [игнор отключен] [закрыт для гостей] / Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
25 сообщений из 28, страница 1 из 2
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37939292
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте.

Не могу понять, почему и Ora 11.2 и SS 2005 XE (другого нет под рукой) не делают join elimitation в следующем случае.
DDL:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
create table tm(id int primary key, m01 int); -- master table
create table td(id int primary key, pid int references tm, d01 int); -- detail table
insert into tm values(1, 100);
insert into tm values(2, 200);
insert into tm values(3, 300);
insert into tm values(4, 400);
insert into tm values(5, 500);
insert into td values(10, 1, 111);
insert into td values(20, 2, 222);
insert into td values(30, 2, 223);
insert into td values(40, 3, 333);
insert into td values(50, 3, 334);
commit;


Query:
Код: sql
1.
select m.* from tm m left join td d on m.id=d.pid;

Этот запрос всегда выдаёт полное кол-во строк из таблицы tm, т.к. тут внешнее соединение. Далее, в select-списке нет ни одного поля из таблицы td ==> соединение здесь вообще можно не проводить.

Тем не менее, получаю вот следующие результаты.
1. Oracle 11.2.0.3.0: hash join таблиц
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
SQL> set autot trace explain
SQL> select m.* from tm m left join td d on m.id=d.pid;
Затрач.время: 00:00:00.00

План выполнения
----------------------------------------------------------
Plan hash value: 100464988

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     5 |   195 |     5  (20)| 00:00:01 |
|*  1 |  HASH JOIN OUTER   |      |     5 |   195 |     5  (20)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| TM   |     5 |   130 |     2   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| TD   |     5 |    65 |     2   (0)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("M"."ID"="D"."PID"(+))
2. MS SQL 2005 Express Edition: nested loops
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
set statistics profile  on;
select m.* from tm m left join td d on m.id=d.pid;
set statistics profile off;

(7 row(s) affected)
Table 'td'. Scan count 1, logical reads 11 ...
Table 'tm'. Scan count 1, logical reads 2 ...

Rows	Executes	StmtText
7	1	select m.* from tm m left join td d on m.id=d.pid;
7	1	  |--Nested Loops(Left Outer Join, WHERE:([misc].[dbo].[tm].[id] as [m].[id]=[misc].[dbo].[td].[pid] as [d].[pid]))
5	1	       |--Clustered Index Scan(OBJECT:([misc].[dbo].[tm].[PK__tm__7C8480AE] AS [m]))
25	5	       |--Clustered Index Scan(OBJECT:([misc].[dbo].[td].[PK__td__7E6CC920] AS [d]))

Кстати, "обратный" запрос, в котором надо получить только поля из detail-таблицы:
Код: sql
1.
select d.* from td d inner join tm m on m.id=d.pid;

- выдаёт разумный план только в Оракле:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
SQL> select d.* from td d join tm m on m.id=d.pid;
Затрач.время: 00:00:00.01

План выполнения
----------------------------------------------------------
Plan hash value: 556202680

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     5 |   195 |     2   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| TD   |     5 |   195 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------
В SQL Server'e - снова чтение двух таблиц + Nested Loops. Только когда detail-таблица становится ведущей в left join'e, SS2005 догадывается не ходить за данными в tm.

Какие будут мнения по этому вопросу ?

PS.
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Data Mining and Real Application Testing options
---------------------------------------------------------------------------------------------------------------------
Microsoft SQL Server 2005 - 9.00.5000.00 (Intel X86) Dec 10 2010 10:56:29 Copyright (c) 1988-2005 Microsoft Corporation Express Edition
with Advanced Services on Windows NT 5.0 (Build 2195: Service Pack 4)
...
Рейтинг: 0 / 0
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37939320
Фотография ScareCrow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторMicrosoft SQL Server 2005
2012 год на дворе.
...
Рейтинг: 0 / 0
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37939321
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ScareCrowавторMicrosoft SQL Server 2005
2012 год на дворе.ну, и что там в SS 2012 для вышеприведенного ?
...
Рейтинг: 0 / 0
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37939516
+100500
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Таблоид, вы оставьте по одной записи в каждой таблице - сравните план, потом по 100000/50000 ...
...
Рейтинг: 0 / 0
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37939528
locky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Таблоид,

ну, во первых, я бы сказал что сравнивать экспресс и энтерпрайз - как минимум грешно.


во вторых я бы сказал, что при тех данных, что использованы в тестовом примере - сервер может вообще планами не заморачиваться, а делать как попало - хоть декарт+фильтрация
...
Рейтинг: 0 / 0
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37939533
locky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ага, сорри, не досмотрел немного (что, вообще говоря, не отменяет того что я сказал выше)

вот это вот "Этот запрос всегда выдаёт полное кол-во строк из таблицы tm, т.к. тут внешнее соединение. Далее, в select-списке нет ни одного поля из таблицы td ==> соединение здесь вообще можно не проводить." - бред
Потому и результат такой.
...
Рейтинг: 0 / 0
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37939542
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
lockyпри тех данных, что использованы в тестовом примере - сервер может вообще планами не заморачиватьсяOK, вот побольше данных:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
create table nx(i int);
commit;
delete from nx;
insert into nx 
select number i
from master..spt_values
where type='P' and number<1000;
----------
delete from td;
delete from tm;

insert into tm(id, m01)
select n1.i*1000+n0.i k, 1
from nx n0, nx n1
where n1.i*1000+n0.i<100000;

insert into td(id, pid, d01)
select n1.i*1000+n0.i k, (n1.i*1000+n0.i)%100000, 1
from nx n0, nx n1
where n1.i*1000+n0.i<500000;

update statistics tm;
update statistics td;
go
SET SHOWPLAN_ALL ON;
go
select m.* from tm m left join td d on m.id=d.pid;
select d.* from td d join tm m on m.id=d.pid;
go
SET SHOWPLAN_ALL OFF;



Результат:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
select m.* from tm m left join td d on m.id=d.pid;
  |--Hash Match(Left Outer Join, HASH:([m].[id])=([d].[pid]), RESIDUAL:([misc].[dbo].[tm].[id] as [m].[id]=[misc].[dbo].[td].[pid] as [d].[pid]))
       |--Clustered Index Scan(OBJECT:([misc].[dbo].[tm].[PK__tm__7C8480AE] AS [m]))
       |--Clustered Index Scan(OBJECT:([misc].[dbo].[td].[PK__td__7E6CC920] AS [d]))
 select d.* from td d join tm m on m.id=d.pid;
  |--Hash Match(Inner Join, HASH:([m].[id])=([d].[pid]), RESIDUAL:([misc].[dbo].[td].[pid] as [d].[pid]=[misc].[dbo].[tm].[id] as [m].[id]))
       |--Clustered Index Scan(OBJECT:([misc].[dbo].[tm].[PK__tm__7C8480AE] AS [m]))
       |--Clustered Index Scan(OBJECT:([misc].[dbo].[td].[PK__td__7E6CC920] AS [d]))
lockyвот это вот <...> - бредБолее подробное объяснение будет ? Вы DDL точно внимательно посмотрели ?
...
Рейтинг: 0 / 0
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37939544
locky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Таблоидlockyвот это вот <...> - бредБолее подробное объяснение будет ? Вы DDL точно внимательно посмотрели ?

Да. Я мало того что его посмотрел, я всё скопировал и выполнил
и что я могу сказать - в исходной таблице tm - 5 строк, а результатом выполнения вашего запроса являются 7 строк, что не в полной мере отвечает заявленном "Этот запрос всегда выдаёт полное кол-во строк из таблицы tm" и уж точно противоречит "соединение здесь вообще можно не проводить."
...
Рейтинг: 0 / 0
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37939545
locky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И, кстати, глубоко по шарабану - внешнее там или унутренее объединение
Исходная посылка - неправильная, следовательно - не следует удивляться тому что реальный результат не соответствует якобы ожидаемому
...
Рейтинг: 0 / 0
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37939549
locky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вот если сделать вот так
Код: sql
1.
select d.* from td d left join tm m on m.id=d.pid;


тогда да, ненужный джойн убирается
...
Рейтинг: 0 / 0
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37939552
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
lockyв исходной таблице tm - 5 строк, а результатом выполнения вашего запроса являются 7 строк,да, пардон: с запросом tm left join td я глупость сморозил, бывает :-)
Но с "обратным" запросом - почему так ?
я про то, что
Код: sql
1.
select d.* from td d INNER join tm m on m.id=d.pid;

и
Код: sql
1.
select d.* from td d LEFT join tm m on m.id=d.pid; 

должны выдавать одинаковое число строк: каждой строке из 'd' может соотв-вать только одна строка из tm. И лезть в tm тут точно нет нужды, ибо не нужно от неё ничего. А он таки лезет, когда там inner join.
...
Рейтинг: 0 / 0
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37939554
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
lockyтогда да, ненужный джойн убираетсяя чуть опоздал со своим ответом.
Так почему этот самый ненужный джойн стал ему нужен при INNER join'e ?
...
Рейтинг: 0 / 0
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37939557
locky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Таблоидlockyтогда да, ненужный джойн убираетсяя чуть опоздал со своим ответом.
Так почему этот самый ненужный джойн стал ему нужен при INNER join'e ?


Потому что результаты запроса - могут быть разными, знаете-ли, при внешнем и внутреннем объединении

Хотя, по хорошему, надо смотреть на trusted констрейнта - и пропускать соединение
...
Рейтинг: 0 / 0
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37939558
locky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Таблоидlockyв исходной таблице tm - 5 строк, а результатом выполнения вашего запроса являются 7 строк,да, пардон: с запросом tm left join td я глупость сморозил, бывает :-)
Но с "обратным" запросом - почему так ?
я про то, что
Код: sql
1.
select d.* from td d INNER join tm m on m.id=d.pid;

и
Код: sql
1.
select d.* from td d LEFT join tm m on m.id=d.pid; 

должны выдавать одинаковое число строк: каждой строке из 'd' может соотв-вать только одна строка из tm. И лезть в tm тут точно нет нужды, ибо не нужно от неё ничего. А он таки лезет, когда там inner join.
Да, "должны". Но могут и "не" :)
...
Рейтинг: 0 / 0
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37939563
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
lockyо хорошему, надо смотреть на trusted констрейнта - и пропускать соединениеDBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS; - не выдал ничего "красным цветом". Да и таблицы-то были наполнены только что и одноразово. Откудова там нарушениям констрейнтов взяться.
Или вы про другое говорите ?
...
Рейтинг: 0 / 0
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37939564
locky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Таблоидlockyо хорошему, надо смотреть на trusted констрейнта - и пропускать соединениеDBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS; - не выдал ничего "красным цветом". Да и таблицы-то были наполнены только что и одноразово. Откудова там нарушениям констрейнтов взяться.
Или вы про другое говорите ?

trsuted у констренйта - не немного не то что "нарушение целостности" :)

в целом я думаю - просто перестраховка
с lj в любом случае результат не поменяется, независимо от состояния FK, в то врмя как ij таки зависит от.
...
Рейтинг: 0 / 0
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37939936
Andrey Sribnyak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ТаблоидНо с "обратным" запросом - почему так ?
я про то, что
Код: sql
1.
select d.* from td d INNER join tm m on m.id=d.pid;

и
Код: sql
1.
select d.* from td d LEFT join tm m on m.id=d.pid; 

должны выдавать одинаковое число строк: каждой строке из 'd' может соотв-вать только одна строка из tm. И лезть в tm тут точно нет нужды, ибо не нужно от неё ничего. А он таки лезет, когда там inner join.


второй так и выдает:

Код: sql
1.
2.
select d.* from dbo.td d LEFT join dbo.tm m on m.id=d.pid;
  |--Clustered Index Scan(OBJECT:([tempdb].[dbo].[td].[PK__td__3213E83FAEC3A5AF] AS [d]))



Код: sql
1.
2.
3.
4.
Microsoft SQL Server 2012 - 11.0.2100.60 (X64) 
	Feb 10 2012 19:39:15 
	Copyright (c) Microsoft Corporation
	Express Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1)
...
Рейтинг: 0 / 0
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37940050
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Andrey Sribnyak,

да, я это вижу. Но вопрос про td inner join tm: почему он при этому начинает лезть в 'tm'.
...
Рейтинг: 0 / 0
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37940170
Фотография SergSuper
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ТаблоидAndrey Sribnyak,

да, я это вижу. Но вопрос про td inner join tm: почему он при этому начинает лезть в 'tm'.а вдруг там две записи?
...
Рейтинг: 0 / 0
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37940177
locky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SergSuperТаблоидAndrey Sribnyak,

да, я это вижу. Но вопрос про td inner join tm: почему он при этому начинает лезть в 'tm'.а вдруг там две записи?
ну, вообще-то, чисто формально такое невозможно
то что в реальной жизни "случается всякое" - это да....
но формально - невозможно
...
Рейтинг: 0 / 0
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37940988
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
On 08/31/2012 07:25 PM, Таблоид wrote:

> select m.* from tm mleft join td don m.id=d.pid;
>
> Этот запрос всегда выдаёт полное кол-во строк из таблицы tm, т.к. тут внешнее
> соединение. Далее, в select-списке нет ни одного поля из таблицы td ==>
> соединение здесь вообще можно не проводить.

0) а нахрена-ж ты тогда вообще JOIN пишешь, если он тебе не нужен ?

1) Кол-во записей в результате может увеличится за счёт JOIN-а.
соответственно, запрос с JOIN-ом и без -- разные запросы.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37941379
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv0) а нахрена-ж ты тогда вообще JOIN пишешь, если он тебе не нужен ?

1) Кол-во записей в результате может увеличится за счёт JOIN-а.
соответственно, запрос с JOIN-ом и без -- разные запросы.0) не я пишу такие запросы, но некоторые мои коллеги (бывшие), чьи авгиевы конюшни приходится разгребать.
1) я уже признал выше свой косяк для этого варианта. Повторяться не буду.
...
Рейтинг: 0 / 0
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37941910
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
lockyну, вообще-то, чисто формально такое невозможно то что в реальной жизни "случается всякое" - это да.... но формально - невозможно
Разное бывает, к сожалению.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
Connected to Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 
Connected as test
 
SQL> create table master(id integer, data varchar2(20));
 
Table created
 
SQL> insert into master values (1, 'Первая строка');
 
1 row inserted
 
SQL> insert into master values (2, 'Вторая строка');
 
1 row inserted
 
SQL> insert into master values (1, 'Третья строка');
 
1 row inserted
 
SQL> create index master_pk on master(id);
 
Index created
 
SQL> alter table master add primary key(id) novalidate;
 
Table altered
 
SQL> insert into master values (3, 'Четвёртая строка');
 
1 row inserted
 
SQL> insert into master values (1, 'Пятая строка');
 
insert into master values (1, 'Пятая строка')
 
ORA-00001: нарушено ограничение уникальности (TEST.SYS_C0011825)
 
SQL> create table detail (id integer, master_id integer references master);
 
Table created
 
SQL> insert into detail values (1, 1);
 
1 row inserted
 
SQL> insert into detail values (2, 2);
 
1 row inserted
 
SQL> explain plan for select d.* from detail d join master m on (d.master_id = m.id);
 
Explained
 
SQL> select * from table(dbms_xplan.display());
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1315321948
----------------------------------------------------------------------------
| Id  | Operation         | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |        |     2 |    52 |     3   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| DETAIL |     2 |    52 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("D"."MASTER_ID" IS NOT NULL)
Note
-----
   - dynamic sampling used for this statement (level=2)
 
17 rows selected
 
SQL> select d.* from detail d join master m on (d.master_id = m.id);
 
                                     ID                               MASTER_ID
--------------------------------------- ---------------------------------------
                                      1                                       1
                                      2                                       2
 
SQL> select * from master;
 
                                     ID DATA
--------------------------------------- --------------------------------------------------------------------------------
                                      1 Первая строка
                                      2 Вторая строка
                                      1 Третья строка
                                      3 Четвёртая строка
 
...
Рейтинг: 0 / 0
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37941955
locky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarerlockyну, вообще-то, чисто формально такое невозможно то что в реальной жизни "случается всякое" - это да.... но формально - невозможно
Разное бывает, к сожалению.


Вот-вот
Однако, хочу отметить - ведь в данном случае PK находится в состоянии not trusted (спасибо novalidate) , так шта....

А вот в том случае, когда PK проверен и всё такое - можно было бы джойн и не делать
...
Рейтинг: 0 / 0
Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
    #37941957
locky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а, стоп, у оракула что - всё наоборот?
джойн убирается хотя не должен был?
...
Рейтинг: 0 / 0
25 сообщений из 28, страница 1 из 2
Форумы / Сравнение СУБД [игнор отключен] [закрыт для гостей] / Не вижу join elimination в Oracle и Sql Server'e для примитивной выборки master-detail
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]