У меня есть таблица 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, но это похоже на регрессию.
Есть ли что-то очевидное в том, почему мой первоначальный подход оказывает такое негативное влияние на производительность?
Есть ли более эффективный способ достижения того же результата?