Вернуть нулевые значения в условном соединении - PullRequest
0 голосов
/ 09 февраля 2019

У меня есть таблица settings и таблица settings_values, которые пересекаются со значением для каждого пользователя.Важно, чтобы я возвращал значение NULL в тех случаях, когда настройка не была включена для пользователя.Также важно, чтобы таблица была высокоэффективной, так как ее будут часто вызывать.

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

setting_id     |     setting_name     |    value     |     user_id
1                    blue                  true            35
2                    red                   NULL            NULL
3                    yellow                false           35
4                    brown                 true            35
5                    black                 NULL            NULL

У меня есть работающее решение, которое работает ниже, но оно создает узкое место в моих запросах к базе данных, что странно, учитывая, что settings имеет только 50 строк, а settings_values только около 20 000.

Мои таблицы структурированы примерно так:

settings:

setting_id     |    setting_name

С параметром setting_id в качестве единственного индекса (первичный ключ)

settings_values:

id      |    setting_id     |    value    |    user_id

При id в качестве первичного ключа, setting_id в качестве первичного ключа, ссылающегося на предыдущую таблицу, value - это varchar, а user_id также имеет индекс.

Мой текущий рабочий код выглядит следующим образом:

SELECT
    s.setting_id,
    s.setting_name,
    sv.value,
    sv.user_id
FROM
    cmssps_settings s
LEFT JOIN cmssps_settings_values sv ON
    s.setting_id = sg.setting_id
    AND sv.user_id = '35';

Кажется, что все работает нормально, кроме узкого места (я получаю 5 возвращенных строк), и я подозреваю, что это JOIN ON, и это вызываетпомедленнее.Я пытался достичь того же результата с помощью JOIN ON WHERE, как это, но я не получаю требуемых результатов NULL (т.е. он возвращает только 3 строки, которые удовлетворяют WHERE):

    SELECT
        s.setting_id,
        s.setting_name,
        sv.value,
        sv.user_id
    FROM
        cmssps_settings s
    LEFT JOIN cmssps_settings_values sv ON
        s.setting_id = sg.setting_id
        WHERE sv.user_id = '35';

Когда я ОБЪЯСНЯЮ оба, я получаю это для первого:

id  | select_type   | table | type  | possible_keys | key   | key_len   | ref   | rows  | Extra
1   | SIMPLE        | s     | ALL   | [NULL]        | [NULL]| [NULL]    | [NULL]| 49    | [NULL]
1   | SIMPLE        | sv    | ref   | user_id       | branch_id | 5     | const | 24    | Using where

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

id  | select_type   | table | type  | possible_keys | key   | key_len   | ref   | rows  | Extra
1   | SIMPLE        | s     | index | [NULL]        | PRIMARY   | 4     | [NULL]| 49    | [NULL]
1   | SIMPLE        | sv    | ref   | user_id       | branch_id | 5     | const | 24    | Using where

Я также пытался вложить запросы и использовать UNION, но это похоже на регрессию.

Есть ли что-то очевидное в том, почему мой первоначальный подход оказывает такое негативное влияние на производительность?

Есть ли более эффективный способ достижения того же результата?

...