Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Incorrect Sorting with UUID Data Type in MariaDB #51883

Closed
@Karem-sobhy

Description

@Karem-sobhy

Laravel Version

11.11.1

PHP Version

8.3.8

Database Driver & Version

MariaDB 11.4.2

Description

When using the new UUID data type in MariaDB, the sorting is incorrect due to byte swapping performed by MariaDB to optimize UUIDv1 storage and indexing.

Details:

MariaDB stores UUID in an index-friendly manner. A UUID of the form llllllll-mmmm-Vhhh-vsss-nnnnnnnnnnnn is stored as:
nnnnnnnnnnnn-vsss-Vhhh-mmmm-llllllll

This format provides a sorting order assuming a UUIDv1 (node and timestamp) is used, where the node is followed by the timestamp. The key aspect is that the timestamps are sequential.

MariaDB does not perform this byte-swapping for UUID versions >= 6:

MariaDB starting with 10.10
Starting from MariaDB 10.10.6 and MariaDB 10.11.5, considering that UUIDv7 and other versions are designed around time ordering, UUIDs version >= 6 are now stored without byte-swapping. Additionally, UUIDs with version >= 8 and variant=0 are now considered invalid (as the standard expects).

Problem:

When Laravel uses Str::orderedUuid() to generate a new ID for a model and insert it, MariaDB sees the version as < 6 and inserts it swapped. Consequently, the UUID is not ordered and not index-friendly, even though the purpose of the ordered UUID function is to ensure order and End of the table insert (Index friendly insert).

Conclusion:

  • Every insert now is "Out of order insert", making it slower.
  • Sorting by the UUID column will not work because it's stored in a different way than the sorted string format.
  • This issue makes the new UUID data type in MariaDB useless and not compatible with Laravel.
  • This makes the old CHAR(36) preferable over the new UUID type, at least when storage wasn't an issue (since UUID is BIN(16)).
  • This behavior is not mentioned in the documentation.

Steps To Reproduce

  1. in .env DB_CONNECTION=mariadb
  2. make model with migration that contains $table->uuid('id')->primary();
  3. use the HasUuids trait inside the model
  4. create some of that model and observe the wrong order that it's stored in the table

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions