Если есть какие-либо недостатки, не используйте первичную таблицу / ключ в операторе соединения - PullRequest
0 голосов
/ 11 сентября 2018

У меня есть следующие таблицы:

users 
    id
    name

departments 
    id
    name

user_departments
    id
    user_id
    name

user_views
    id
    user_id
    views   

Выше id является первичным ключом во всех таблицах, а user_id и Department_id являются внешними ключами.

Мне нужно сделать запрос для просмотра пользователямив отделе.Поэтому я сделал такой запрос

SELECT user_views.view FROM user_views JOIN user_departments ON user_views.user_id = user_departments.user_id WHERE user_departments.department_id = 1234;

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

Есть ли у производительности или другой недостаток отсутствие использования первичных таблиц и соответствующего первичного ключа в соединении?Я использую Postgres SQL, однако у меня тоже есть вопрос о MySQL.

ОБНОВЛЕНИЕ: Альтернативные версии, о которых я говорю

SELECT user_views.view FROM users JOIN user_views ON users.id = user_views.user_id JOIN user_departments ON users.id = user_departments.user_id WHERE user_departments.department_id = 1234;

SELECT user_views.view FROM users JOIN user_views ON users.id = user_views.user_id JOIN user_departments ON users.id = user_departments.user_id JOIN departments ON departments.id = user_departments.department_id  WHERE departments.id = 1234;

Ответы [ 2 ]

0 голосов
/ 12 сентября 2018

PK (первичные ключи), FK (внешние ключи) и другие ограничения не нужны для запроса. Любые 2 таблицы могут быть осмысленно объединены при любых условиях. Значения базовых таблиц и результатов запроса (условие для строки, находящейся в таблице или нет в ней) являются необходимыми и достаточными. Ограничения позволяют СУБД запрещать связанные недопустимые состояния базы данных и оптимизировать. Напишите запрос, который возвращает интересующие вас строки.

Требуется объединить 2 таблицы со своими FK в 3-й таблице
Почему совпадения первичного ключа / внешнего ключа не используются для объединений?
Есть ли эмпирическое правило для построения запроса SQL из понятного человеку описания?

Когда выполняются ограничения, определенные запросы, которые в противном случае иногда возвращали бы разные результаты, всегда возвращали один и тот же результат. Тогда, если у вас есть выбор, использование индексированных наборов столбцов, которые обычно являются PK и FK, а не теми, которые этого не делают, может повысить производительность. Но это не относится к ПК и ФК. Фактически мы добавляем индексы для наборов столбцов, когда ожидаем, что обслуживание индекса стоит повышения производительности запросов. ПК и ФК - это особый случай.

0 голосов
/ 11 сентября 2018

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

убедитесь, что у вас правильный индекс в столбцах ON и WHERE *

    SELECT user_views.view 
    FROM user_views 
    JOIN user_departments ON user_views.user_id = user_departments.user_id 
    WHERE user_departments.department_id = 123

в вашем случае

on  table  user_views composite  index on (user_id, view)  

добавлен столбец представления для того, чтобы значение непосредственно формировало индекс, а также избегало доступа к таблице данных

on table user_departments index on (department_id, user_id)

таким образом, представление правильно управляется ..

Обновлено для OP обновленная версия

в силу того, что все таблицы заполнены первичным и внешним ключами, разница между двумя запросами должна быть очень мала. и стратегии, принятые движком SQL

SELECT user_views.view 
FROM users JOIN user_views ON users.id = user_views.user_id 
JOIN user_departments ON users.id = user_departments.user_id 
WHERE user_departments.department_id = 1234;


SELECT user_views.view 
FROM users 
JOIN user_views ON users.id = user_views.user_id 
JOIN user_departments ON users.id = user_departments.user_id 
JOIN departments ON departments.id = user_departments.department_id  
WHERE departments.id = 1234;

Наилучшая производительность может быть получена при использовании составного индекса, получающего всю информацию для фильтрации и выбираемого непосредственно в таблице индексов и избегающего доступа (и пустой траты времени) к данным таблицы.

...