Без глубокого понимания стоит задать себе непреложное правило "у каждой таблицы должен быть primary key". В дальнейшем, когда-нибудь можно будет достичь нирваны ситуации когда pk не должно быть.
Константин, хз. Говорю же, я смутно эту систему понимаю. primary_key по моему разумению ставится на уникальное значение, которое может выступать однозначным указателем. В таблице brands_state может быть два одинаковых значения id_brand, например когда бренд принадлежит двум группам. Или два бренда одной группе. То есть в поле id_brand (id_group) значение неуникально. А foreign_key указывает, (опять же, как я это понимаю), что значение поля id_brand может принимать весь диапазон значений brands.id и в случае удаления/изменения brands.id выполняется какое то действие с таблицей brands_state, обеспечивающее целостность данных.
primary key - определяет уникальную строку. Про то, что он может быть из одного поля речи нет. Если уникальность задают два поля - то и PK будет состоять из двух полей.
Плюс два foreign key, т.к. это значения-ссылки и будет хорошо, если база сможет проверять существование строк, на которые вы ссылаетесь.
Так и не понял зачем все рекомендуют на таблицу brands_state ставить primary key, если это таблица связей.
Там два foreign keys.
Я бы не ставил (да и не ставлю на такие таблицы связей pk, они в них не нужны).
UP:
Если pk это попытка сделать связь уникальной (чтобы дубли не порождались), то это вопрос к логике приложения, который бездумно дублирует строки, состоящие из двух полей внешних ключей, а не к constraint'ам SQL.
Dark_Dante, вам там нужны foreign keys для целостности данных.
Ставить 2 foreign key дополнительно еще как и составной primary key учитывая что кроме них там вообще ничего больше не будет (там 2 поля), это вообще для чего? Для уникальности?
На скорость влиять не будет в таблице связей.
На самом деле ситуация такая. Есть семь таблиц, которые объединены через одну, связывающую. Примерно как на схемке. Связывающая таблица состоит из, примерно, 147 млн записей. Выбирается все это дело SELECTOM с INNER JOIN'aми. И вот все это дело несчадно тормозит. Индексы на всех полях в этой связывающей таблице стоят. Вот бьюсь, чтобы ускорить выборку...
Dark_Dante, я бы уже попробовал создать ключ и посмотреть будут ли изменения (если нет, удалил бы).
Индексы выбраны ли правильные или наоборот они замедляют работу (EXPLAIN смотреть надо, пробовать разные варианты).
А вот там 147 млн записей, актуальны ли они все? Может устаревшие есть (ну там по времени)? Можно было бы создать таблицу архивную и скинуть туда то, что не актуально на данный момент (записи более года назад), а в основной хранить только до года. Тоже оптимизация как никак.
Denis Holub, А как узнать ускоряет ли индекс или замедляет работу базы? По Explain'у все поля eq_ref, кроме двух - они ref - на оба идет WHERE. В общем я туп в этом деле. Я как в тумане от непонимания структуры данных и принципах работы БД, хожу, спотыкаюсь, набиваю шишки :)
Насчет актуальности... в принципе... можно разбить на несколько таблиц по актуальности (ну или частоте обращений). Идея хорошая, я над ней подумаю =)
Dark_Dante, вот этой информации про 150 млн записей, индексирование всех полей, тормозящий запрос и не хватает в вашем исходном вопросе. И здесь исследование начинают обычно с проверки планов выполнения запросов. Обычно здесь-то и выясняются причины проблем. Без планов запросов можно много теорий наплодить. Например, в случае двух таблиц данных и одной таблицы связей, как на рисунке, всё может тормозить, если все 150 млн брендов сидят в одной группе, и вы пытаетесь запросом вытащить все бренды из этой группы. Даже если всё индексировано - тут индексы не помогли бы.
Может, вам вообще нужно в сторону фасетного поиска смотреть.
Denis Holub, Ну на простом примере более понятно :) Смысл то тот же остался, только масштабы другие :) Вот например узнал что примари кей можно на несколько полей ставить. А я на одно ставил, а mysql ругался типа значение неуникальное. Я аж всю голову сломал.