UUID в Laravel: Общие вопросы
Вопрос 1. Когда нужно использовать UUID? В каких случаях
UUID отлично подходят для нескольких случаев:
- Генерация уникальных идентификаторов для моделей и отсутствие необходимости беспокоиться о коллизиях (дубликатах)
- Генерация уникальных идентификаторов для моделей и отсутствие необходимости беспокоиться о раскрытии количества записей в базе данных
- Генерация уникальных идентификаторов для моделей и отсутствие необходимости беспокоиться о порядке расположения записей в базе данных
Если мы посмотрим на UUID V4 (который выглядит следующим образом: f47ac10b-58cc-4372-a567-0e02b2c3d479
), то можем быть уверены, что генерируемые значения всегда будут уникальными. Вероятность столкновения составляет менее 1 к 2,71 квинтиллиона (очень мало!), поэтому их можно смело использовать для своих моделей. Ещё одно преимущество — возможность скрыть детали в URL. Сколько раз вы видели такой URL?
domain.com/shop/orders/1596115
Это говорит, что в базе данных имеется по крайней мере 1596115 заказов. И люди могут попытаться изменить это число, чтобы узнать, есть ли ещё заказы. Но если вы используете UUID, то можете скрыть эту информацию:
domain.com/shop/orders/f47ac10b-58cc-4372-a567-0e02b2c3d479
Теперь пользователи не будут знать, сколько у вас заказов, и у них не будет возможности правильно угадать следующий или предыдущий заказ (если только им не повезёт!). Это также повышает уровень безопасности, поскольку вы не можете просто изменить 1 цифру в URL и попытаться увидеть чужой заказ. Что также особенно полезно, если у вас многопользовательское приложение.
Для генерации UUID V4 в Laravel можно использовать:
Ramsey\Uuid\Uuid::uuid4()->toString();
// Или
Illuminate\Support\Str::uuid()->toString();
В результате вы получите строку следующего вида: 81239d02-9334-4051-b72f-e3409dc4310a
. Хелпер Str
является обёрткой вокруг библиотеки Ramsey
, поэтому можно использовать любой из них.
Вопрос 2. Сколько места занимает UUID
Если мы сравним размер поля UUID с полем bigInt
, то увидим, что UUID занимает в 2 раза больше места. Это связано с тем, что UUID хранится в виде строки, а bigInt
— в виде числа.
Вопрос 3. Являются ли UUID медленными
Если мы сравним скорость работы поля UUID с полем bigInt
, то увидим, что UUID в 2 раза медленнее. Это связано с тем, что UUID хранится в виде строки, а bigInt
— в виде числа. Но это заметно только в том случае, если у вас большая база данных. Если у вас маленькая база данных — вы не заметите никакой разницы.
Вопрос 4. UUID vs ULID. В чем разница
Основное различие между UUID и ULID заключается в способе их генерации. UUID генерируется с помощью генератора случайных чисел, а ULID — с помощью временной метки и генератора случайных чисел. Это означает, что ULID можно сортировать, а UUID — нет. Это также означает, что ULID не так уникален, как UUID, поскольку в нем используется временная метка. Но для большинства случаев он все же достаточно уникален.
Если мы хотим посмотреть, как выглядят UUID и ULID, мы можем сгенерировать несколько из них:
dd(
\Illuminate\Support\Str::uuid()->toString(),
\Illuminate\Support\Str::ulid()->toBase32()
);
Что даст следующие результаты:
UUID
28f39d8d-4972-4d59-a642-248c453a6662
c8e43384-17b6-44ce-8d16-0aefc6e3eb4c
ULID
01H6ET312T05WVXVGSF0V0KXW7
01H6ET73YNZMJ2JWJPDHS5ADKC
Как видно, ULID был сгенерирован по порядку, а UUID — нет.
Вопрос 5. UUID как первичный ключ или отдельный столбец
Говоря об использовании UUID в качестве первичного ключа или отдельного столбца, необходимо учитывать несколько моментов:
- Использование UUID в качестве первичного ключа сделает работу базы данных медленнее, так как придётся искать строку вместо числа.
- Использование UUID в качестве первичного ключа замедлит процесс вставки, поскольку MySQL придётся обновлять индекс, чтобы он был "упорядочен" для повышения производительности. Это займёт больше времени, так как это строка, а не
int
, который уже упорядочен. - Использование UUID в качестве первичного ключа займёт больше места, так как придётся хранить строку, а не число.
- Использование UUID в качестве первичного ключа сделает вашу базу данных более защищённой, так как будет сложнее угадать следующую или предыдущую запись. Однако за это приходится расплачиваться скоростью.
Более эффективным может быть следующий подход:
- Использование UUID в качестве отдельного столбца повышает вероятность случайного использования неправильного идентификатора, поскольку в этом случае придётся работать с двумя идентификаторами.
- Использование UUID в качестве отдельного столбца позволит использовать более короткий идентификатор для отношений.
Однако все зависит от того, какая производительность требуется вашей базе данных. Если данных немного, то UUID в качестве первичного ключа может быть вполне достаточно, но если важна скорость — используйте его как отдельный столбец.