Skip to content
About
Main content

Identity by position

How does a reader map bytes to fields, and why is position-based identity silently fatal?

The question: bytes in, fields out

A reader has bytes on disk and a schema in its head. It must decide which bytes correspond to which field. The rule that makes this decision is the . The entire set of legal operations on a schema follows from the identity rule you choose.

There are three common rules. In each one, "identity" means: what do I use to say "this is the same field as before"?

Identity ruleThe field is identified byTypical formats
Positionits ordinal (first, second, third column)headerless CSV, some binary row formats
Namea stringJSON, CSV with header, Avro (by field name), many databases
IDan integer assigned when the column is created such as Iceberg, Protocol Buffers field numbers

Identity is the ordinal. It has zero lookup cost, and it is the only option for formats that carry no description of themselves (nothing in the file says what the columns are).

What it does to changes:

  • Rename is free and meaningless (the name is not used anywhere).
  • Insert in the middle, reorder and drop are catastrophic. And, the important point, : neighbouring columns are often of compatible types, so you get wrong values instead of an error.

That is why headerless delimited text is the worst-behaved interface in common use. Ravi's CSV is an example:

old file:   S1001,12.5,1999      <- shipment_id, volume_kg, price_cents
new file:   S1001,3.2,12.5,1999  <- shipment_id, weight_kg, volume_kg, price_cents

partner loader (still expects 3 columns by position):
  shipment_id = S1001
  volume_kg   = 3.2      <- actually weight
  price_cents = 12.5     <- actually volume  (a number, so it parses fine)
  (the fourth value is ignored or causes a quiet truncation)