К сожалению реалии таковы, что просто написать "никак" не получится, т.к. MySQL всё еще занимает лидирующие позиции по использованию в веб разработке, не смотря на все его недостатки.
🙈 Многие по-умолчанию сохраняют
UUID в CHAR(36) и не переживают по этому поводу. Действительно, если кол-во записей в вашей таблице < 50к, то вы скорее всего не заметите никаких проблем. Но что если в какой-то из таблиц их больше полумиллиона?Хранить как BINARY.
🔨 Благо с выходом 8й версии MySQL часть танцев с бубном была перенесена в коробку и
UUID_TO_BIN / BIN_TO_UUID уже делают всё за тебя. Они производят сжатие 32 символов (36 или более с разделителями) до 16-битного формата или обратно до формата, который снова можно прочесть.INSERT INTO t VALUES(UUID_TO_BIN(UUID()));👍 Мы уже получим буст, и очень неплохой, т.к. MySQL отлично индексирует
SELECT BIN_TO_UUID(id) FROM t;
BINARY, даже лучше, чем привычный автоинкрементный INT. И всё бы ничего, если бы не кластерный индекс, который как раз и используется у PRIMARY KEY. Это значит, что для его оптимизации мы должны иметь и упорядоченные UUID в базе. Но как это сделать?❗️Для этого можно использовать
UUID первой версии, в которой содержатся биты связанные со временем. А во время использования UUID_TO_BIN / BIN_TO_UUID использовать второй (необязательный, логический) аргумент:INSERT INTO t VALUES (UUID_TO_BIN (UUID (), true));Именно он переупорядочит биты, связанные со временем, так, чтобы последовательные сгенерированные значения были упорядочены и в индексе.
📊 Ну и самое интересное — сравнение!
📌 Выходит, что при малом кол-ве записей, наш оптимизированный
UUID работает медленнее остальных, при этом при 500к он обгоняет по показателям INT. И здесь возникает совсем другая история, а именно кол-во потребляемой памяти для большого кол-ва записей :) Безусловно, генерируемые id — довольно удобный инструмент, но всегда следует хорошо спроектировать решение в голове, прежде чем внедрить.
#PHP #MySQL #middle #source