SqlServer: Join двух таблиц с отношением "one to one"
От: Аноним  
Дата: 14.11.13 14:06
Оценка:
Можно ли как-то сделать более оптимально Join по двум таблицам с отношением "one to one"?

Есть две таблицы с primary key "id". У одной из них есть FK на другую.
Стандартный "INNER JOIN" работает не достаточно быстро (если вместо двух таблиц сделать одну, то выборка будет идти в 3-5 раз быстрее).

Причина в том, что как и положено для INNER JOIN найдя id в одной таблице SqlServer находит все соответствующие значения в другой (Execution Plan показывает, что на это уходит почти все время).

Если бы я делал выборку с клиента, то я бы открыл два ридера (по каждому на таблицу) и считывал бы обе таблицы сверху вниз (за один проход), паралельно соединяя полученные данные вместе (например в один класс).
Тут выгода получается в том, что не нужно постоянно бегать по индексу, а можно просто сверху вниз считывать таблицы.

Можно ли как-то SqlServer-у "сказать", что таблицы связаны как один к одному и можно просто их парарельно считывать и возвращать результат вместе?
Re: SqlServer: Join двух таблиц с отношением "one to one"
От: vmpire Россия  
Дата: 14.11.13 14:30
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Можно ли как-то SqlServer-у "сказать", что таблицы связаны как один к одному и можно просто их парарельно считывать и возвращать результат вместе?

Сделайте индекс на поле, по которому идёт соединение, в обоих таблицах
Re[2]: SqlServer: Join двух таблиц с отношением "one to one"
От: Аноним  
Дата: 14.11.13 14:33
Оценка:
Здравствуйте, vmpire, Вы писали:

V>Здравствуйте, Аноним, Вы писали:


А>>Можно ли как-то SqlServer-у "сказать", что таблицы связаны как один к одному и можно просто их парарельно считывать и возвращать результат вместе?

V>Сделайте индекс на поле, по которому идёт соединение, в обоих таблицах

уже есть два индекса в каждой из таблиц, которые используют "IncludeColumn" для всех оставшихся колонок.
Соединение идет по PK, но индекс реально помогает, ускоряя весь процесс в 2-3 раза.
Но все-равно это не достаточно быстро (намного медленнее, чем с одной таблицей)
Re: SqlServer: Join двух таблиц с отношением "one to one"
От: bl-blx Россия http://yegodm.blogspot.com
Дата: 14.11.13 14:43
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Можно ли как-то сделать более оптимально Join по двум таблицам с отношением "one to one"?

А>Можно ли как-то SqlServer-у "сказать", что таблицы связаны как один к одному и можно просто их парарельно считывать и возвращать результат вместе?

Создайте indexed view с inner join — получится денормализованное 1-1.
El pueblo unido jamás será vencido.
Re: SqlServer: Join двух таблиц с отношением "one to one"
От: igor_ku  
Дата: 14.11.13 15:09
Оценка:
Здравствуйте, Аноним, Вы писали:

A>найдя id в одной таблице SqlServer находит все соответствующие значения в другой


Это слегка противоречит отношению one-to-one — в нём "все" это только одна запись в другой таблице. Может вы что-то недоговариваете?

А>Можно ли как-то SqlServer-у "сказать", что таблицы связаны как один к одному и можно просто их парарельно считывать и возвращать результат вместе?


Попробуйте крайний случай — использовать Join hints. Это именно крайний случай, потому что sql server optimizer сам выбирает самый оптимальный вариант. Но попробовать можно.
Re[2]: SqlServer: Join двух таблиц с отношением "one to one"
От: Аноним  
Дата: 14.11.13 15:31
Оценка:
Здравствуйте, bl-blx, Вы писали:

BB>Здравствуйте, Аноним, Вы писали:


А>>Можно ли как-то сделать более оптимально Join по двум таблицам с отношением "one to one"?

А>>Можно ли как-то SqlServer-у "сказать", что таблицы связаны как один к одному и можно просто их парарельно считывать и возвращать результат вместе?

BB>Создайте indexed view с inner join — получится денормализованное 1-1.


Спасбио за совет. View создал, попробовал несколько INDEX-ов, но ни один из них не используется при выполнении запроса.
Execution Plan показывает только использование индексов на таблицах.
Пробовал создавать индексы по id из двух таблиц, по id из одной таблицы, пробовал делать IncludeColumn.
Не подскажите какой именно индекс нужно создать на View в моем случае?
Re[3]: SqlServer: Join двух таблиц с отношением "one to one"
От: vmpire Россия  
Дата: 14.11.13 15:31
Оценка:
Здравствуйте, Аноним, Вы писали:

А>>>Можно ли как-то SqlServer-у "сказать", что таблицы связаны как один к одному и можно просто их парарельно считывать и возвращать результат вместе?

V>>Сделайте индекс на поле, по которому идёт соединение, в обоих таблицах

А>уже есть два индекса в каждой из таблиц, которые используют "IncludeColumn" для всех оставшихся колонок.

А>Но все-равно это не достаточно быстро (намного медленнее, чем с одной таблицей)
Ну так таблиц-то две
Естественно, это медленнее.
И потом, если бы даже (теоретически) SQL Server знал, что искомая запись только одна, это бы ускорило процесс максимум в два раза в случае nested loops (так как это единственную запись всё равно нужно ещё найти).

Посмотрите план выполнения, если там merge join по этим колонкам и нет bookmark lookup то быстрее уже не будет, если только не закэшировать результат заранее, как посоветовал bl-blx
Re[3]: SqlServer: Join двух таблиц с отношением "one to one"
От: bl-blx Россия http://yegodm.blogspot.com
Дата: 14.11.13 18:28
Оценка:
Здравствуйте, Аноним, Вы писали:

BB>>Создайте indexed view с inner join — получится денормализованное 1-1.


А>Спасбио за совет. View создал, попробовал несколько INDEX-ов, но ни один из них не используется при выполнении запроса.

А>Execution Plan показывает только использование индексов на таблицах.
А>Пробовал создавать индексы по id из двух таблиц, по id из одной таблицы, пробовал делать IncludeColumn.
А>Не подскажите какой именно индекс нужно создать на View в моем случае?

Если у вас SQLServer ниже чем Enterprise Edition, то нужно указывать NOEXPAND hint, иначе оптимизатор будет
игнорировать вьюху:
select * from dbo.MyOneToOneView with (noexpand)
El pueblo unido jamás será vencido.
Re[4]: SqlServer: Join двух таблиц с отношением "one to one"
От: ZAMUNDA Земля для жалоб и предложений
Дата: 14.11.13 19:47
Оценка:
Здравствуйте, vmpire, Вы писали:

А>>уже есть два индекса в каждой из таблиц, которые используют "IncludeColumn" для всех оставшихся колонок.

А>>Но все-равно это не достаточно быстро (намного медленнее, чем с одной таблицей)
Фрагментация индексов? Загруженность диска? Оперативки хватает?
Тип ключевых полей?

V>Ну так таблиц-то две

V>Естественно, это медленнее.
V>И потом, если бы даже (теоретически) SQL Server знал, что искомая запись только одна, это бы ускорило процесс максимум в два раза в случае
nested loops (так как это единственную запись всё равно нужно ещё найти).
MERGE JOIN быстрее NESTED LOOPS IMHO. Если запись одна, то добавь TOP 1.
Наука изощряет ум; ученье вострит память.
(c) Козьма Прутков
Re[4]: SqlServer: Join двух таблиц с отношением "one to one"
От: Аноним  
Дата: 15.11.13 00:18
Оценка:
Здравствуйте, bl-blx, Вы писали:

BB>Здравствуйте, Аноним, Вы писали:


BB>>>Создайте indexed view с inner join — получится денормализованное 1-1.


А>>Спасбио за совет. View создал, попробовал несколько INDEX-ов, но ни один из них не используется при выполнении запроса.

А>>Execution Plan показывает только использование индексов на таблицах.
А>>Пробовал создавать индексы по id из двух таблиц, по id из одной таблицы, пробовал делать IncludeColumn.
А>>Не подскажите какой именно индекс нужно создать на View в моем случае?

BB>Если у вас SQLServer ниже чем Enterprise Edition, то нужно указывать NOEXPAND hint, иначе оптимизатор будет

BB>игнорировать вьюху:
BB>
BB>select * from dbo.MyOneToOneView with (noexpand)
BB>


большое спасибо. Так реально летает. Запрос выполняется также быстро как на одной таблице без JOIN-а
Re: SqlServer: Join двух таблиц с отношением "one to one"
От: wildwind Россия  
Дата: 15.11.13 16:13
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>Стандартный "INNER JOIN" работает не достаточно быстро (если вместо двух таблиц сделать одну, то выборка будет идти в 3-5 раз быстрее).


Покажи план и статистику.
И второй вопрос, "достаточно быстро" это сколько?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.