mysql выбор между уникальным ключом и первичным ключом для идентификатора пользователя - PullRequest
0 голосов
/ 22 марта 2020

Я создаю базу данных пользователей ... Я хочу отделить номер пользователя и мобильного телефона от таблицы 'user' и создать для нее другую таблицу (user_cellphone (table))

, но у меня проблема с выбором лучшего index!

в таблице user_cellphone, мы получаем user_id и номер мобильного телефона ... но все запросы SELECT больше основаны на user_id, поэтому я хочу знать, лучше ли выбрать столбец user_id в качестве первичного ключа или не !!!

(также у каждого пользователя есть только один номер мобильного телефона!)

, какой из этих двух вариантов лучше?

CREATE TABLE `user_cellphone_num` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
    `cellphone_country_code` SMALLINT UNSIGNED NOT NULL,
    `cellphone_num` BIGINT UNSIGNED NOT NULL,
    `user_id` INT UNSIGNED NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE INDEX `cellphone` (`cellphone_country_code`, `cellphone_num`),
    UNIQUE INDEX `user_id` (`user_id`)
)


CREATE TABLE `user_cellphone_num` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
    `cellphone_country_code` SMALLINT UNSIGNED NOT NULL,
    `cellphone_num` BIGINT UNSIGNED NOT NULL,
    `user_id` INT UNSIGNED NOT NULL,
    PRIMARY KEY (`user_id`),
    UNIQUE INDEX `id` (`id`),
    UNIQUE INDEX `cellphone` (`cellphone_country_code`, `cellphone_num`)
)

выбрав «user_id» в качестве первичного ключа или просто установите «user_id» в качестве уникального ключа ?! Есть ли здесь что-то другое в производительности? (Я имею в виду, когда у меня миллионы строк)

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

select u.*,cell.* FROM user AS u LEFT JOIN user_cellphone AS cell ON cell.user_id = u.id

, поэтому один из этих вариантов даст мне лучшую производительность для некоторых запросов как это?

Ответы [ 2 ]

1 голос
/ 23 марта 2020

Могу ли я предложить некоторые с трудом завоеванные советы по проектированию данных?

Не используйте телефонные номера в качестве какого-либо уникального или первичного ключа.

Почему бы и нет?

  • Иногда несколько человек используют один номер.

  • Иногда люди составляют фальшивые номера.

  • Люди перемежают цифры в зависимости от контекста. Для моих соседей мой номер (978) 555-4321. Для покупателя в Нидерландах это +1,978,555,4321. Можете ли вы написать программу, чтобы упорядочить эти цифры? Конечно. Можете ли вы написать правильную программу для этого? Нет. Зачем пытаться. Просто возьмите все, что вам дадут.

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

Внимательно прочтите это. https://github.com/google/libphonenumber/blob/master/FALSEHOODS.md

0 голосов
/ 23 марта 2020

Таблицы InnoDB хранятся в виде кластеризованного индекса , также называемого индексной таблицей . Если таблица имеет ПЕРВИЧНЫЙ КЛЮЧ, то он используется в качестве ключа для кластеризованного индекса. Другой UNIQUE KEY является вторичным индексом.

Запросы, в которых вы просматриваете строки по кластерному индексу, несколько эффективнее, чем использование вторичного индекса, даже если этот вторичный индекс является уникальным индексом. Так что, если вы хотите оптимизировать для наиболее распространенного запроса, который вы говорите, по user_id, то было бы неплохо сделать этот кластеризованный индекс.

В вашем случае это было бы странно разделить мобильные телефоны в отдельную таблицу, но затем сделать только user_id ПЕРВИЧНЫМ КЛЮЧОМ. Это означает, что в этой таблице может существовать только одна строка на user_id. Я ожидал, что вы разделили мобильные телефоны в отдельную таблицу, чтобы у каждого пользователя было несколько телефонных номеров.

Вы можете получить такое же преимущество кластерного индекса, если просто убедитесь, что user_id - это первый столбец в составном ключе:

CREATE TABLE `user_cellphone_num` (
    `user_id` INT UNSIGNED NOT NULL,
    `num` TINYINT UNSIGNED NOT NULL,
    `cellphone_country_code` SMALLINT UNSIGNED NOT NULL,
    `cellphone_num` BIGINT UNSIGNED NOT NULL,
    PRIMARY KEY (`user_id`, `num`)
)

Таким образом, запрос типа SELECT ... FROM user_cellphone_num WHERE user_id = ? будет соответствовать одной или нескольким строкам, но это будет эффективный поиск, поскольку он ищет первый столбец кластеризованного индекс.

Ссылка: https://dev.mysql.com/doc/refman/8.0/en/innodb-index-types.html

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