Должен ли я использовать SQL JOIN или IN предложение? - PullRequest
3 голосов
/ 29 октября 2011

У меня вопрос о наилучшем подходе. Я не уверен, какой подход лучше, когда данные считаются переменными по размеру.

Рассмотрим следующие 3 ТАБЛИЦЫ:

СОТРУДНИК

EMPLOYEE_ID, EMP_NAME

ПРОЕКТ

PROJECT_ID, PROJ_NAME

EMP_PROJ (многие ко многим из двух таблиц выше)

EMPLOYEE_ID, PROJECT_ID

Проблема : По идентификатору EmployeeID найти ВСЕХ сотрудников ВСЕХ проектов, с которыми связан данный Сотрудник.

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

SELECT EMP_NAME FROM EMPLOYEE
WHERE EMPLOYEE_ID IN (
    SELECT EMPLOYEE_ID FROM EMP_PROJ    
    WHERE PROJECT_ID IN (
        SELECT PROJECT_ID FROM EMP_PROJ p, EMPLOYEE e
        WHERE p.EMPLOYEE_ID = E.EMPLOYEE_ID 
        AND  E.EMPLOYEE_ID = 123)

идти

select c.EMP_NAME FROM
(SELECT PROJECT_ID FROM EMP_PROJ 
  WHERE EMPLOYEE_ID = 123) a
JOIN 
EMP_PROJ b
ON a.PROJECT_ID = b.PROJECT_ID
JOIN 
EMPLOYEE c
ON b.EMPLOYEE_ID = c.EMPLOYEE_ID

На данный момент я ожидаю около 5000 Сотрудников и Проектов каждый ... но понятия не имею, какие существуют отношения многие-многие. Какой подход вы бы порекомендовали? спасибо!

EDIT: План выполнения подхода 1

"Hash Join  (cost=86.55..106.11 rows=200 width=98)"
"  Hash Cond: (employee.employee_id = emp_proj.employee_id)"
"  ->  Seq Scan on employee  (cost=0.00..16.10 rows=610 width=102)"
"  ->  Hash  (cost=85.07..85.07 rows=118 width=4)"
"        ->  HashAggregate  (cost=83.89..85.07 rows=118 width=4)"
"              ->  Hash Semi Join  (cost=45.27..83.60 rows=118 width=4)"
"                    Hash Cond: (emp_proj.project_id = p.project_id)"
"                    ->  Seq Scan on emp_proj  (cost=0.00..31.40 rows=2140 width=8)"
"                    ->  Hash  (cost=45.13..45.13 rows=11 width=4)"
"                          ->  Nested Loop  (cost=0.00..45.13 rows=11 width=4)"
"                                ->  Index Scan using employee_pkey on employee e  (cost=0.00..8.27 rows=1 width=4)"
"                                      Index Cond: (employee_id = 123)"
"                                ->  Seq Scan on emp_proj p  (cost=0.00..36.75 rows=11 width=8)"
"                                      Filter: (p.employee_id = 123)"

План выполнения подхода 2:

"Nested Loop  (cost=60.61..112.29 rows=118 width=98)"
"  ->  Index Scan using employee_pkey on employee e  (cost=0.00..8.27 rows=1 width=4)"
"        Index Cond: (employee_id = 123)"
"  ->  Hash Join  (cost=60.61..102.84 rows=118 width=102)"
"        Hash Cond: (b.employee_id = c.employee_id)"
"        ->  Hash Join  (cost=36.89..77.49 rows=118 width=8)"
"              Hash Cond: (b.project_id = p.project_id)"
"              ->  Seq Scan on emp_proj b  (cost=0.00..31.40 rows=2140 width=8)"
"              ->  Hash  (cost=36.75..36.75 rows=11 width=8)"
"                    ->  Seq Scan on emp_proj p  (cost=0.00..36.75 rows=11 width=8)"
"                          Filter: (employee_id = 123)"
"        ->  Hash  (cost=16.10..16.10 rows=610 width=102)"
"              ->  Seq Scan on employee c  (cost=0.00..16.10 rows=610 width=102)"

Похоже, план выполнения подхода 2 немного лучше, потому что «стоимость» равна 60, а не 85 подхода 1. Это правильный способ проанализировать это?

Откуда знать, что это будет справедливо даже для всех видов множества комбинаций?

1 Ответ

4 голосов
/ 29 октября 2011

Оба подхода могут вызывать неоптимальную производительность, поскольку оба используют подзапросы, которые оптимизированы эффективно или не зависят от СУБД.

Я бы предложил избегать подзапросов и использовать JOIN для того, что предполагается использовать, например:

Edit:

Я исправил и упростил мой пример:

select coll.EMP_NAME
from EMP_PROJ ep1
inner join EMP_PROJ ep2 on ep1.PROJECT_ID = ep2.PROJECT_ID
inner join EMPLOYEE coll on ep2.EMPLOYEE_ID = coll.EMPLOYEE_ID
where ep1.EMPLOYEE_ID = 123

Я думаю, следует отметить, что вполне законно ссылаться на одну и ту же таблицу более одного раза с различными псевдонимами в одном запросе. На запрос это логически «выглядит» как две отдельные таблицы, которые имеют одинаковую структуру и данные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...