Я генерирую UUID, используя UUID_TO_BIN(UUID(), true), и сохраняю их как BINARY(16).
Однако при получении значений:
var uuid = dataReader.GetGuid(name);
Console.WriteLine(uuid.ToString());
Я печатаю строку uuid, но это не та же строка, что и при запуске SELECT BIN_TO_UUID("col") в столбце.
Что я делаю не так?
OldGuids в строке подключения на true, но все равно получил тот же неверный uuid.UUID_TO_BIN(UUID(), true) и сохраняю их как BINARY(16), заключается в том, что, согласно моим показаниям, я считаю, что это наиболее эффективный способ хранения uuid и использования их в качестве первичных ключей.Спасибо
GetGuid(col)
3da4ec11-3568-cfb4-92aa-b42e99eb957f
BIN_TO_UUID(col)
11eca43d-6835-b4cf-92aa-b42e99eb957f
BIN_TO_UUID(col, true)
6835b4cf-a43d-11ec-92aa-b42e99eb957fв чем разница между этими двумя руководствами? Можете ли вы разделить ценности, которые, по вашему мнению, должны быть одинаковыми? Кроме того: BIN_TO_UUID("col") не является обратным тому, как вы сгенерировали UUID, но это может быть упущением.





Вам нужно вручную исправить проблему с порядком байтов следующим образом:
var v = dataReader.GetValue(dataReader.GetOrdinal(name));
if (v is byte[] data && data.Length == 16)
return new Guid(data, bigEndian: true);
Причина этого в том, что MySQL создает строку GUID в побайтовом порядке, а .NET преобразует первые три раздела в целочисленную форму с порядком байтов по умолчанию. MySqlDataReader.GetGuid по умолчанию не меняет порядок байтов, поэтому в целом это будет LE.
Это отличный ответ, но для его использования ОП придется переключиться с MySql.Data на MySqlConnector.
Спасибо, что указали на мою ошибку. Однако ключевая проблема связана с разным порядком байтов при чтении на двух языках, независимо от второго параметра. Предполагая, что двоичный идентификатор равен 0x010203040506..., BIN_TO_UUID выведет его как 01020304-0506..., а .net по умолчанию будет читать его с прямым порядком байтов как 0x04030201, 0x0605, ...
Если вы создаете и сохраняете их с помощью UUID_TO_BIN(UUID(), true), вам нужно будет прочитать их обратно с помощью BIN_TO_UUID(columnName, true).
MySqlDataReader.GetGuid в MySQL Connector/NET (т. е. MySql.Data) не имеет возможности сделать это. Вот некоторые варианты:
BIN_TO_UUID(columnName, true) везде, удалите Old Guids=true из строки подключения и используйте GetGuid для чтения возвращаемой строки.true при использовании UUID_TO_BIN для хранения GUID (и просто используйте UUID_TO_BIN(UUID())); это расположит байты в том порядке, который ожидает GetGuid.GuidFormat = TimeSwapBinary16 в строке подключения.О, я не знал, что мне нужно преобразовать его обратно, используя флаг true! Используя (1), читая столбец как BIN_TO_UUID(columnName, true) и используя GetGuid, возвращаемый Guid получает правильное значение, например, такое же, как SELECT BIN_TO_UUID(columnName, true). Но тогда я мог бы просто использовать GetString, чтобы прочитать это. При использовании варианта (2) будет ли GetGuid читаться двоичные данные напрямую?
Причина, по которой я использовал флаг true, заключается в том, что где-то в документации MySql я читал, что он более производительный (с использованием MAC-адреса сервера). Но я не знаю, применимо ли это сейчас, и правильно ли я вообще понял документацию. Я предпочитаю просто использовать UUID_TO_BIN(UUID()), если это так эффективно. Но база данных уже используется уже пару лет, поэтому я не думаю, что смогу сейчас изменить uuid.
UUID_TO_BIN(x, true) может повысить производительность, если столбец проиндексирован, благодаря способу хранения значений, основанных на времени. В противном случае в этом нет необходимости. Однако, как только вы начнете использовать флаг , true, вам следует использовать его последовательно для записи и чтения GUID из этого столбца, чтобы вы гарантированно получали правильные значения.
Хорошо, хорошо, потому что эти uuid являются первичными ключами, поэтому они индексируются. Знаете ли вы, повлияет ли смена оборудования на производительность? С этого момента будет другой MAC-адрес, на котором основан uuid.
@Karmeye MAC-адрес хранится в последних шести байтах UUID v1, поэтому имеет значение (для порядка UUID в индексе), только если два UUID v1 были сгенерированы в течение одного и того же 100-наносекундного интервала.
Ого, вы хорошо разбираетесь в этих вопросах! Правильно ли я вас понимаю, что улучшение производительности с использованием только флага true относится к последовательной генерации uuid? Итак, при запросе к базе данных, например, с помощью SELECT, используется ли флаг true или нет, не влияет на производительность?
@Karmeye Это правильно. Флаг true используется для изменения GUID, чтобы они с большей вероятностью были добавлены в виде новых строк в конце таблицы, а не вставлены в середину таблицы, что приведет к перемещению существующих данных. . Использование флага true или его отсутствие не влияет на производительность поиска существующих данных.
Производительность поиска была единственной причиной, по которой я добавил этот флаг. Мне следовало сначала спросить здесь :) Возможно, в какой-то момент я конвертирую все uuid. Спасибо!
Если вы конвертируете значение на входе, я ожидаю, что вам придется конвертировать его на выходе. Но я ничего не знаю о MySQL и uuids.