как упорядочивание по UUID работает в PostgreSQL?

Есть ли какая-либо гарантия порядка при использовании uuid_generate_v1() в postgresql?

Если да, то гарантии на машину или не важно на какой машине был сгенерирован UUID? Поскольку V1 UUID определяется по отметке времени + MAC-адресу, упорядочивает ли Postgres внутреннюю часть по отметке времени, а затем по MAC-адресу?

Могу ли я «заказать» столбец типа UUID и ожидать, что он всегда будет работать (кажется, работает)?

Я хочу сгенерировать UUID на нескольких машинах (с помощью postgresql uuid_generate_v1()), скопировать их в один экземпляр Postgres, а затем упорядочить по столбцу UUID. Он должен гарантировать порядок по машинам, а не порядок UUID всех машин.


person Thiago Sayão    schedule 05.04.2017    source источник
comment
Временная метка может быть извлечена из UUID (v1). Вы видели это? stackoverflow.com/questions/37713131/   -  person Andy Carlson    schedule 05.04.2017
comment
Я видел это, но упорядочивание без предложенной функции в этом ответе, похоже, тоже работает (с простым столбцом ORDER BY). Не уверен, что он независим от машины.   -  person Thiago Sayão    schedule 05.04.2017
comment
Не существует универсального порядка UUID (или даже расположения байтов). Однако PostgreSQL имеет зависимый от реализации порядок UUID, как и SQL Server (и это не гарантируется; .NET имеет другой порядок, чем SQL Server, хотя оба являются творениями Microsoft). ). Таким образом, порядок PostgreSQL будет согласованным. Если uuid_generate_v1 удобен для индекса PgSQL и/или хорошо упорядочен в PgSQL на основе «времени», это конкретная деталь.   -  person user2864740    schedule 01.11.2018
comment
Несмотря на это, я не могу найти никакой технической документации, но я предполагаю, что порядок «гарантирован» внутри PostgreSQL. Изменение порядка будет крупным критическим изменением и может зависеть от двоичного кодирования UUID. Если есть какая-то причина, по которой эти данные могут быть упорядочены вне от PgSQL, тогда... не полагайтесь на них D:   -  person user2864740    schedule 01.11.2018


Ответы (2)


UUID не предназначены для заказа.

Если вы хотите выбрать свои записи на основе порядка создания, вы должны использовать метку времени date_creation, столбец auto-increment (не для вашего конкретного случая) или создать свои собственные идентификаторы с алгоритмом, гарантирующим порядок; Например, объедините метку времени + UUID или метку времени + автоинкремент.

Вы можете создать function в базе данных для более позднего варианта.

person Guillaume F.    schedule 05.04.2017
comment
Проблема с метками времени заключается в том, что они не гарантируют уникальность. Однако объединение временной метки + uuid уникально и может быть решением для меня. Вопрос в том, конкатенация timestamp + uuid быстрее, чем выполнение предложения order by timestamp, uuid? - person Robin Jonsson; 05.07.2017
comment
Отметка времени Integer будет намного быстрее, чем отметка времени String. Конкатенация сделает ваш индекс медленнее, чем использование двух специализированных столбцов. - person Guillaume F.; 05.07.2017
comment
UUID представляют собой 128-битные числа (минус несколько битов) и могут быть хорошо упорядочены... в зависимости от 1) того, как они генерируются (в данном случае UUIDv1) и 2) как они упорядочены. Этот ответ не касается обоих. В частности, в базах данных есть особый способ упорядочения UUID (и он будет таким же быстрым, как и любой другой порядок). Как этот конкретный способ согласуется с UUID, сгенерированным через v1? Это может не совпадать (по времени), но это важные детали. Тривиальный контрпример к тому, что UUID не предназначены для заказа, — это newsquentialid() в SQL Server. - person user2864740; 01.11.2018
comment
(В приведенном выше комментарии я расширяю область действия UUID за пределы 5 «официально определенных» типов генерации + варианты, что кажется честной игрой..) - person user2864740; 01.11.2018
comment
timeuuid в кассандре заказан - person user1870400; 01.05.2019

Хотя ни в коем случае не окончательный ответ - т.е. «определено ли поведение для всех установок PostgreSQL?», этот SQL (для SQL Server) для проверки порядка каждого байта в GUID. Возможно, понадобятся некоторые настройки для PostgreSQL.

Генерация такого сопоставления должна позволить увидеть, «упорядочивается ли конкретная структура UUID (один из четко определенных типов или иным образом) в PostgreSQL определенным образом».

With UIDs As (--                           0 1 2 3  4 5  6 7  8 9  A B C D E F
            Select ID = 'F', UID = cast ('00000000-0000-0000-0000-000000000011' as uniqueidentifier)
    Union   Select ID = 'E', UID = cast ('00000000-0000-0000-0000-000000001100' as uniqueidentifier)
    Union   Select ID = 'D', UID = cast ('00000000-0000-0000-0000-000000110000' as uniqueidentifier)
    Union   Select ID = 'C', UID = cast ('00000000-0000-0000-0000-000011000000' as uniqueidentifier)
    Union   Select ID = 'B', UID = cast ('00000000-0000-0000-0000-001100000000' as uniqueidentifier)
    Union   Select ID = 'A', UID = cast ('00000000-0000-0000-0000-110000000000' as uniqueidentifier)
    Union   Select ID = '9', UID = cast ('00000000-0000-0000-0011-000000000000' as uniqueidentifier)
    Union   Select ID = '8', UID = cast ('00000000-0000-0000-1100-000000000000' as uniqueidentifier)
    Union   Select ID = '7', UID = cast ('00000000-0000-0011-0000-000000000000' as uniqueidentifier)
    Union   Select ID = '6', UID = cast ('00000000-0000-1100-0000-000000000000' as uniqueidentifier)
    Union   Select ID = '5', UID = cast ('00000000-0011-0000-0000-000000000000' as uniqueidentifier)
    Union   Select ID = '4', UID = cast ('00000000-1100-0000-0000-000000000000' as uniqueidentifier)
    Union   Select ID = '3', UID = cast ('00000011-0000-0000-0000-000000000000' as uniqueidentifier)
    Union   Select ID = '2', UID = cast ('00001100-0000-0000-0000-000000000000' as uniqueidentifier)
    Union   Select ID = '1', UID = cast ('00110000-0000-0000-0000-000000000000' as uniqueidentifier)
    Union   Select ID = '0', UID = cast ('11000000-0000-0000-0000-000000000000' as uniqueidentifier)
)
Select * From UIDs Order By UID desc

В SQL Server (2014 г., и совпадает с порядком в SQL Server 2005) по убыванию:

Position by highest-to-lowest value:

A B C D E F | 8 9 | 7 6 | 5 4 | 3 2 1 0

Поскольку newsequentialid SQL Server использует этот порядок для генерации GUID, удобного для индекса, поведение, вероятно, никогда не изменится. SQL Server также должен поддерживать это поведение во всех системах для поддержки репликации. Таким образом, если бы вопрос касался SQL Server, я бы определенно сказал, что «существует согласованный порядок идентификаторов GUID в SQL Server», на который можно абсолютно положиться в SQL Server.

Однако этот порядок отличается от порядка GUID в .NET, и я не удивлюсь, если порядок в PostgreSQL будет другим. «Переворачивающиеся» различия в SQL Server связаны с тем, что он следует упорядочение COM GUID в варианте 2 (также известном как прямой порядок следования байтов); это делается даже для UUID «Вариант 1». (Однако кажется более произвольным, почему сами группы упорядочены справа налево: больше истории Microsoft?)

Остается интересный вопрос: где/как это указано для заказа в PostgreSQL? Если это не точно определено, можно ли по-прежнему рассматривать реализацию как аксиому поведения?

Также см. этот вопрос для получения более подробной информации об UUID SQL Server; и вкусные подробности о том, «почему» существуют эти различия.

person user2864740    schedule 02.11.2018
comment
Для всех, кто пришел сюда, интересовался выводом этого скрипта из Postgresql, с небольшой модификацией вывод хорошо упорядочен 0 1 2 3 ... F. (PostgreSQL 9.5.14 на x86_64-pc-linux-gnu, скомпилированный gcc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609, 64-разрядная версия) - person Codism; 05.12.2018