Почти любой таблице нужен первичный ключ. Это поле или их комбинация, которая однозначно определяет запись. Первичный ключ уникален и не допускает NULL (обычный UNIQUE допускает его). Для первичного ключа автоматом строится btree индекс.

Первичные ключи бывают естественными и суррогатными. К первым относятся различные международные коды и стандарты отрасли. Например, коды аэропортов назначаются однажды и не меняются. Есть всемирные классификаторы болезней. На заводах каждая деталь имеет свой код — это и есть естественные ключи.

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

Особая ситуация с людьми: попытки найти у них естественный ключ обречены на провал. Во-первых, комбинации ФИО, даты и места рождения не уникальны. Редко, но бывают полные тезки, родившиеся в один год. Кроме того, у людей все меняется. Женщины выходят замуж: была Иванова, стала Петрова. Мужчины тоже меняют имена, хоть и реже (знаю два случая). На прошлой работе коллега совершил гендерный переход: сменил имя и пол (не удивлюсь, если при этом пофиксил дату рождения).

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

Номера телефонов и паспортов — все это небезопасно и меняется со временем.

На тему того, чем должен быть первичный ключ — счетчиком или UUID — я уже писал. Вкратце, счетчик делает вас заложником БД: только она знает, каким будет очередное значение. Это плохо подходит для распределенных систем. UUID отвязывает вас от БД, а кроме того, в нем можно хранить метаданные. Например, UUIDv7 содержит время, поэтому подлежит сортировке и заменяет поле created_at. Идентификатор Snowflake, придуманный в Твиттере, хранит коды региона, датацентра, сервера и другие метаданные.

В больших дружных компаниях (банках, заводах, тюрьмах) сотрудникам назначают коды — нечто среднее между числами и идентификаторами. Бейджик — это и есть код сотрудника. Если сотрудник изменит имя или пол, админам не придется заводить новую запись: они перебьют поля в админке.

Не всегда роль и человек совпадают один к одному. Скажем, один человек может быть двумя студентами одновременно (разные факультеты, очное-заочное и так далее). В этом случае есть таблица person, а таблица students ссылается на человека по внешнему ключу. Если гражданка Иванова сменила фамилию на Петрову, оба факультета это увидят. По аналогии в больших компаниях один человек может занимать несколько должностей, быть пациентом многих отделений клиники и так далее. Это надо учитывать.