![]() |
![]() |
![]() |
|
Что лучше условие В или внутреннее соединение с таблицей? | ☑ | ||
---|---|---|---|---|
0
Черный всадник
08.04.09
✎
12:57
|
Собственно как будет лучше так:
... ГДЕ Таблица_1.Поле_1 В (ВЫБРАТЬ Таблица_2.Поле_2 ИЗ Таблица_2 КАК Таблица_2 ) ... или так: ... ИЗ Таблица_1 КАК Таблица_1 ВНУТРЕННЕЕ СОЕДИНЕНИЕ Таблица_2 КАК Таблица_2 ПО Таблица_1.Поле_1 = Таблица_2.Поле_2 ... Таблица Таблица_2 может содержать несколько десятков тясяч записей. |
|||
1
Mort
08.04.09
✎
12:58
|
ИМХО соединение.
|
|||
2
sur0k
08.04.09
✎
13:02
|
(0) Сделай замер производительности
|
|||
3
Черный всадник
08.04.09
✎
13:02
|
(1) Я то же думаю соединение, но уверенности нет. Условие В рекомендовано для списков из 100-300 записей.
|
|||
4
Черный всадник
08.04.09
✎
13:03
|
(2) Наверняка тут кто-то уже делал. Сейчас стенда под рукой нет :(
|
|||
5
ShoGUN
08.04.09
✎
13:05
|
Я думаю что соединение, плюс - оно читабельней.
|
|||
6
Кириллка
08.04.09
✎
13:05
|
(0)так это разные механизмы и используются для разных вещей.
Их сравнивать можно только для какой-то конкретной задачи. |
|||
7
Черный всадник
08.04.09
✎
13:12
|
(6) Что неконкретного в (0)? Мне необходимо сделать выборку из таблицы Таблица_1 с описаными условиями. Я понимаю, что это разные механизмы, вот и спрашиваю как получше сделать.
|
|||
8
Кириллка
08.04.09
✎
13:15
|
(7)на пальцах объяснить?
|
|||
9
Кириллка
08.04.09
✎
13:16
|
+8 стоп, не буду объяснять, пока ты не уберешь из своего профиля Интересы: Проектирование БД
|
|||
10
Джинн
08.04.09
✎
13:16
|
Должно быть пофигу с точки зрения производительности.
|
|||
11
Черный всадник
08.04.09
✎
13:17
|
(8) Объясни.
|
|||
12
dimoff
08.04.09
✎
13:18
|
По простой логике В должно отрабатывать как минимум не дольше, чем внутреннее соединение.
|
|||
13
dimoff
08.04.09
✎
13:19
|
Так что на чем основываются имхи (0) и (1) вообще непонятно.
|
|||
14
Черный всадник
08.04.09
✎
13:22
|
(10, 12, 13) Опираясь на логику Если поле Поле_2 индексировано?
|
|||
15
Кириллка
08.04.09
✎
13:22
|
В первой таблице:
Строка1 Строка2 Строка3 Строка4 Во второй таблице: Строка1 Строка2 Строка3 Строка3 Строка3 Строка4 Результатом в случае с IN будет: Строка1 Строка2 Строка3 Строка4 Результатом в случае с INNER JOIN будет: Строка1 Строка2 Строка3 Строка3 Строка3 Строка4 |
|||
16
Черный всадник
08.04.09
✎
13:24
|
(15) Сори, забыл - дублирование строк в результате не принципиально.
|
|||
17
Черный всадник
08.04.09
✎
15:02
|
Больше никто этим не интересовался что ли...
|
|||
18
Defender aka LINN
08.04.09
✎
15:05
|
запрос в "В" отрабатывает на каждую строку исходной таблицы.
Вопросы? |
|||
19
73
08.04.09
✎
15:05
|
По моему опыту соединение быстрее.
|
|||
20
FreeArcher
08.04.09
✎
15:09
|
Запросы будут работать по разному:
1. В Будет производится сервером обход по таблице и по каждой строке проверятся условие. 2. соединение Возьмутся обе таблице проиндексируются (если нет индексов) по полю через которое происходит соединение. А затем будет произведена связь по индексу и выйдет результирующая таблица. вариант 2 должен быть эффективнее на больших объемах хотя бы из-за индексов и внутренней оптимизации СУБД. |
|||
21
Stepa86
08.04.09
✎
15:10
|
(18) а если временной таблице
|
|||
22
Stepa86
08.04.09
✎
15:11
|
+(21)а если временной таблицей заменить запрос в "В"
|
|||
23
nop
08.04.09
✎
15:11
|
я думаю что лучше пакетный запрос + "В"
|
|||
24
Defender aka LINN
08.04.09
✎
15:11
|
(21) А разница?
|
|||
25
Kolyasik
08.04.09
✎
15:11
|
сделай через временные таблицы проиндексируй поля, а потом соедини...
|
|||
26
Sadovnikov
08.04.09
✎
15:12
|
(0) Ситуации разные бывают. Есть примеры, когда замена INNER JOIN на IN сократила время выполнения запроса с нескольких минут до нескольких секунд.
|
|||
27
Stepa86
08.04.09
✎
15:12
|
(24) "отрабатывает на каждую строку исходной таблицы" означает, что каждый раз запрос выполняется? или результат там кэшируется
|
|||
28
Черный всадник
08.04.09
✎
15:13
|
(20) Вот я подозревал, что как то так должно происходить. Но все как то времени не было проверить :) Спасибо.
|
|||
29
Sadovnikov
08.04.09
✎
15:13
|
(20) "проиндексируются (если нет индексов) " - ничего не путаешь?
|
|||
30
Невский Александр
08.04.09
✎
15:14
|
(6) +1
|
|||
31
orefkov
08.04.09
✎
15:17
|
(26)
Если поле в присоединяемой таблице не индексированное? |
|||
32
Кириллка
08.04.09
✎
15:17
|
(20)Странно говорить об внутренней оптимизации СУБД (какой?) и индексах (они есть?).
|
|||
33
Sadovnikov
08.04.09
✎
15:20
|
(31) Не совсем понял...
|
|||
34
Черный всадник
08.04.09
✎
15:25
|
(26) В мем случае таблица_1 содержит в среднем 1 000 000 записей, таблица_2 в среднем 5 000 записей. Поле)1 и Поле_2 индексированы. Поле_2 содержит уникальные значения, значения в Поле_1 могут повторяться. Тут будет лучше INNER JOIN или IN?
|
|||
35
Sadovnikov
08.04.09
✎
15:27
|
(34) Я бы сделал ставку на JOIN. Тольк по возможности LEFT JOIN, а не INNER.
А еще бы большую ставку я сделал на тест данной ситуации :) Проверить-то не долго. |
|||
36
Черный всадник
08.04.09
✎
15:30
|
(35) Ночью сервак освободится потесчу. Почему LEFT, а не INNER? Тогда ведь придется условие по NULL накладывать, чтоб отсечь лишние записи.
|
|||
37
fisher
08.04.09
✎
15:31
|
(0) Тут сложно сказать. Ведь какой именно план выполнения запроса будет выбран оптимизатором запросов - неизвестно. Это зависит от многих факторов (как явных, так и неявных).
На практике рекомендовано, всегда когда только можно (и логично) использовать соединения, а не альтернативные способы. Считается, что в этом случае больше вероятность того, что оптимизатором запросов будет выбран оптимальный план выполнения. Т.е. изначально лучше всего следовать общим рекомендациям (использовать JOIN, где можно), а когда уже речь идёт об оптимизации выполнения конкретного тяжелого запроса - анализировать план выполнения на предмет узких мест и пробовать варианты. |
|||
38
fisher
08.04.09
✎
15:36
|
(36) В данном конкретном простом случае (0), рискну предположить что план выполнения будет выбран одинаковый (или сопоставимый по скорости).
|
|||
39
Sadovnikov
08.04.09
✎
15:47
|
(0)
Set NoCount On Declare @Счетчик Int, @Начало DateTime, @Конец DateTime Create Table T1 (P1 Int) Create Table T2 (P1 Int) Set @Счетчик = 0 While @Счетчик < 1000000 Begin Insert Into T1 Values (@Счетчик) Set @Счетчик = @Счетчик + 1 End Set @Счетчик = 0 While @Счетчик < 5000 Begin Insert Into T2 Values (@Счетчик) Set @Счетчик = @Счетчик + 1 End Create Index _1 On T1 (P1) Create Index _2 On T2 (P1) Set @Счетчик = 0 While @Счетчик < 10 Begin Set @Начало = GETDATE() Select * From T1 (NoLock) Inner Join T2 (NoLock) On T1.P1 = T2.P1 Set @Конец = GETDATE() Print 'JOIN ' + Str(DATEDIFF(ms, @Начало, @Конец)) Set @Начало = GETDATE() Select * From T1 (NoLock) Where T1.P1 In (Select P1 From T2 (NoLock)) Set @Конец = GETDATE() Print 'IN ' + Str(DATEDIFF(ms, @Начало, @Конец)) Set @Счетчик = @Счетчик + 1 End Drop Table T1 Drop Table T2 . Результат: JOIN 96 IN 30 JOIN 93 IN 16 JOIN 93 IN 16 JOIN 110 IN 13 JOIN 110 IN 16 JOIN 93 IN 16 JOIN 90 IN 0 JOIN 96 IN 30 JOIN 80 IN 13 JOIN 110 IN 0 |
|||
40
Черный всадник
08.04.09
✎
15:49
|
(39) Спасибо :) Придется переписывать...
|
|||
41
Широкий
08.04.09
✎
15:55
|
(39) В первом запросе выводятся все поля, а во втором только первой таблицы - не справедливо
|
|||
42
Леха Дум
08.04.09
✎
15:56
|
(39) а если поменять местами порядок выборки сначала IN потом JOIN? Кэш на сервере не влияет на результат?
|
|||
43
Черный всадник
08.04.09
✎
15:57
|
(42) Они уже должны быть в кэше
|
|||
44
Леха Дум
08.04.09
✎
16:02
|
(43) хотя да, временные таблы сразу в кэше, но все же если поменять местами?
|
|||
45
Sadovnikov
08.04.09
✎
16:10
|
(44) Попробуй. А то я таблицы уже грохнул - лень ждать, пока они снова заполнятся...
А еще - кто помнит как программно кэши чистить? |
|||
46
Леха Дум
08.04.09
✎
16:12
|
(45) уже, от перемены мест слагаемых сумма практически не меняется :)
|
|||
47
Кириллка
08.04.09
✎
16:36
|
(45)
DBCC DROPCLEANBUFFERS –- дает возможность тестировать запросы при незаполненном буфере данных DBCC FREEPROCCACHE –- дает возможность тестирования запросов при незаполненном кэше планов исполнения. |
|||
48
fisher
08.04.09
✎
17:16
|
(39) Считаю данный тест нифига не показательным. На его основе ни в коем случае нельзя делать вывод, что IN производительнее JOIN. Обязательно нужно сравнивать в боевых условиях. На этом примере в самом деле для IN был сформирован более оптимальный план выполнения. Если модифицировать пример или наполнение таблиц - результат может обратный получиться.
Когда я на первой попавшейся рабочей базе тестанул (на примере таблицы дока и его табличной части), то получил одинаковые планы выполнения. |
|||
49
Sadovnikov
08.04.09
✎
21:38
|
(47) Пасиб!
(48) +1. Был взят самый простой пример. Причем, пример, результаты которого противоречат моему предположению в (35). Каждый случай надо рассматривать отдельно на реальных боевых данных и железе. Именно по этому в классе, отвечающем за фильтры в запросе, сделали свойство - как фильтровать. С ипользованием In или Join. Скуль, зараза, штука хитрая :) |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |