ryanwinchester / uuidv7

UUIDv7 for Elixir (and Ecto)
MIT License
34 stars 3 forks source link

Should I add options for millisecond and nanosec precision? #2

Closed ryanwinchester closed 7 months ago

ryanwinchester commented 7 months ago

The question is in the title

Schultzer commented 7 months ago

Yes

ryanwinchester commented 7 months ago

guess we need to switch to parameterized type then for the ecto stuff?

Schultzer commented 7 months ago

guess we need to switch to parameterized type then for the ecto stuff?

Does the precision default to nanoseconds?

ryanwinchester commented 7 months ago

Does the precision default to nanoseconds?

It's so hard to find info on this.

ryanwinchester commented 7 months ago

I've been (low-effort) looking around for this kind of info (without diving too deep) for the last couple of weeks.

Only lately have I figured out:

iex(7)> :erlang.system_info(:os_system_time_source)
[
  function: :clock_gettime,
  clock_id: :CLOCK_REALTIME,
  resolution: 1000000,
  parallel: :yes,
  time: 1712613910574298000
]

this suggests my system is microseconds according to the resolution...

but System.system_time(:native) returns a nanosecond timestamp and

iex(9)> :erlang.convert_time_unit(1, :second, :native)
1000000000

is nanoseconds...

Schultzer commented 7 months ago

Does the precision default to nanoseconds?

It's so hard to find info on this.

Sorry, I meant, does the current implementation default to nanoseconds, not the specification. I would learn on default to highest precision and make it configurable to lower it. Since with higher precision the ordering would be more precise.

ryanwinchester commented 7 months ago

Does the precision default to nanoseconds?

It's so hard to find info on this.

Sorry, I meant, does the current implementation default to nanoseconds, not the specification. I would learn on default to highest precision and make it configurable to lower it. Since with higher precision the ordering would be more precise.

The spec is milliseconds default with optional extra granularity up to nanoseconds.

There are other UUID libraries out there (either for, or supporting v7) but they just use the default milliseconds and I wanted something with more time granularity. I defaulted to microseconds (for now), to be safe without wasting random bits, but now I'm wondering if I should have defaulted to the spec default (milliseconds) and make the rest configurable, or just go straight to only nanoseconds....

Schultzer commented 7 months ago

I want to emphasize that the point of v7, as you know, is to get a stable ordering of UUID to avoid including an inserted_at column in an order by. With that being said, there is nothing saved by excluding nanoseconds; the storage space would be the same, and there would likely not be any gains in cache coherence. But the pain will be felt if records are stored so close that they conflict; in that case, you will lose the order. Precision, in my opinion, is king in this case. We want deterministic ordering of records.

ryanwinchester commented 7 months ago

Sorry I lied, it was up to 12 bits of sub-millisecond precision which isn't quite nanoseconds. (I haven't read it in a while) We can optionally add a counter on top of that, though.

ryanwinchester commented 7 months ago

I'm going to work in this, with a counter.