← haandev

The anatomy of data languages: bytes, names and a spectrum

There is no such thing as a file on a disk. File, row, document, message — all of them are names given by programs looking at bytes. This small dislocation reframes both SQL's five sublanguages and the categories we sort systems into.

Abstract

The standard opening line of a database course — "SQL consists of five sublanguages" — carries three conceptual errors stacked on top of one another. This piece tries to resolve all three with a single thesis: on a disk there are only bytes; file, row, document and message are names given by the programs looking at those bytes; and the distinction between "file system / database / message queue" is not a difference in kind but a difference in the degree of that naming. The thesis is not new — it is a generalised reading of the literature on data independence (Codd, 1970; ANSI/SPARC, 1975) and "one size does not fit all" (Stonebraker & Çetintemel, 2005). The contribution is not in the claim but in the framing: turning the five language categories from a taxonomy into a measuring instrument.

1. The wrong opening line

The classic opening of a database course is a known quantity: "SQL consists of five sublanguages — DDL, DML, DQL, DCL and TCL." The sentence is not technically wrong, but historically it is upside down.

Evidence 1 — the terms are older than SQL

The terms "Data Description Language" and "Data Manipulation Language" were set out by CODASYL's Data Base Task Group in its April 1971 report; the same report introduces the concepts of schema and subschema. They were defined not for the relational but for the network data model. Chamberlin and Boyce's SEQUEL paper, meanwhile, is dated 1974. So DDL and DML were invented three years before SQL was born, for a model that was SQL's rival.

Evidence 2 — the standard does not use this taxonomy

ISO/IEC 9075-2, the official definition of SQL, sorts statements not into "DDL/DML" but into classes such as SQL-schema statements, SQL-data statements, SQL-transaction statements and SQL-session statements. "DQL" does not appear in the standard at all; in the standard's text SELECT is a data statement. The fivefold taxonomy is a product of pedagogy, not of the standard.

Evidence 3 — non-SQL systems use the same labels

Apache Cassandra's official documentation has separate sections for Data Definition and Data Manipulation. Transaction theory (Gray, 1981) and access control (Saltzer & Schroeder, 1975) were formulated independently of any language from the very beginning.

These three pieces of evidence point the same way: the five categories do not belong to SQL. But the correction doesn't end there, because two further errors sit underneath it. The second: system categories such as "database", "file system" and "message queue" are not as sharp as they are taken to be. The third and deepest: the units these systems claim to operate on — file, row, document, message — are not real entities either.

Below we start at the very bottom and climb: first the byte, then the names, then the boundary violations, and finally the spectrum.

2. Layer zero: there is no such thing as a "file"

2.1 The thesis

The only thing that physically exists on a disk is bytes — addressed, ordered, uninterpreted bytes. What we call a "file" is a group name given to some of those bytes by a computer program called a file system. A file does not live on the disk; it lives in the file system's interpretation. A program that reads the same disk without a file system driver sees no files at all; it sees only bytes.

The same operation repeats at every layer. MongoDB takes a group of bytes and calls it a "document", and groups of documents a "collection". A SQL engine calls a group of bytes a "cell", arrays of cells "rows", and sets of rows a "table". Kafka calls the same bytes a "message" and a "topic". None of these add anything to the bytes; every one of them is nothing but a naming. Ontologically, document, row, file and message have the same status: labels an interpreting program has stuck onto bytes.

File system (ext4)calls this range of bytesthe file «/var/data.db»SQLitecalls this range of bytes«users table, row 42»Kafkacalls this range of bytes«orders, offset 917»4A3F12C07E05B1229D40006EF318A75C2B91D80466EA337F0x00000xFFFF0x4A30 – 0x4B10the only thing physically present on the disk: addressable bytes
Three programs look at the same address range and see three different entities. None adds anything to the bytes; each merely puts a name on them.

2.2 The interpretation stack is recursive

This view makes a beautifully nested picture visible. In the eyes of the file system, SQLite is a single file. But look at the same bytes through SQLite's eyes and the file disappears; tables and rows appear in its place. A row inside it plays exactly the role in SQLite's universe that the file plays in the file system's: an addressable, named group of bytes.

The question of which name is "real" has no answer, because neither is real — what is real are the bytes underneath; the names belong to the program doing the looking.

addressable bytesno interpreter — raw reality/var/lib/app/data.dbext4 names it this wayusersSQLite names it this wayrow — id = 42the table engine names it this waycell — emailthe row layout names it this way6D 68 6F 7A 6F 67 6C 75 40 2E 2E 2Ethe name each layer produces is the next layer's raw bytes
Nowhere in the stack is there a privileged layer. The innermost cell and the outermost block device are different rounds of the same operation. The stack is arbitrary; the material is fixed.

2.3 Historical evidence: disks without files really do exist

Let's take the thought experiment one step further: if we formatted a disk with no file system on it, laid out to store rows and columns directly, that disk would contain no files at all. Not from the absence of files, but from the absence of a program to call those bytes files.

This did not stay a thought experiment:

A file is not a property of the disk but a property of the looking.

2.4 How new is this thesis, really? (Not at all)

What is being said here has an academic name: data independence. It is the very heart of Codd's 1970 paper A Relational Model of Data for Large Shared Data Banks and of the ANSI/SPARC three-schema architecture (1975) that followed it: the internal layer — bytes, pages, indexes — the conceptual layer — tables, rows — and the external view layer are independent of one another.

"There is no such thing as a row on the disk; it is a concept of the logical schema" has been the first chapter of database textbooks for fifty years. The only thing this piece does is generalise the sentence by one step: a file has exactly the same status.

That generalisation is not foreign either. In the operating systems literature the file system is already described plainly as "an abstraction layer over a block device". Its counterpart in programming language theory is direct: the separation of data from its interpretation, the principle that bits have no meaning without a type or an interpretation. The matter of naming and binding is a subject in its own right in the systems literature — Saltzer's Naming and Binding of Objects (1978) is the canonical text.

So the thesis isn't original; it has been moved. It applies what the database community says about its own layers to the whole storage stack.

2.5 Objection: isn't a byte an interpretation too?

Yes. Magnetic flux transitions, charge levels in NAND cells, error correcting codes, 512B/4K sector translations — a "byte" is an abstraction too, and there are further layers beneath it. The turtles go all the way down.

The reason this piece stops at the byte is not ontological but pragmatic: the byte is the lowest level below the software layer, and it offers a universal, stable, addressable frame of reference. Every interpreting program in the stack looks at the same byte space; the layers underneath it vary with the hardware and are inaccessible to software. The byte is chosen as the zero point because it is the common denominator of the discussion — not because it is absolute reality.

3. The grammar of naming: five questions

So how do these interpreting programs differ from one another? This is where the five layers come in — but now we can define them from the right place. DDL, DML, DQL, DCL and TCL are the five questions every program that puts names on bytes is obliged to answer.

#QuestionSQL labelTheoretical basis
1How are names defined? Which groups of bytes get called what — table, collection, topic, directory. It changes not the data but the naming scheme; it establishes a name space.CREATE ALTER DROPThe notion of a schema — CODASYL DBTG (1971); ANSI/SPARC conceptual layer (1975)
2How are the named bytes changed? The transition from one state to another.INSERT UPDATE DELETEState transformation — Gray (1981)
3How are the bytes reached through a name? What we call a query is a description of the path from a name to bytes.SELECTData independence and relational algebra — Codd (1970)
4Who may touch which names? Permission is always granted at the level of names; nobody defines a permission over "512 bytes starting at 0x4A3F".GRANT REVOKEThe access matrix — Saltzer & Schroeder (1975)
5When do changes become "real"? The guarantee that the bytes a name points at look the same, and consistent, to everyone looking at the same moment.COMMIT ROLLBACKThe transaction concept, ACID — Gray (1981)

The detail in the answer to the fourth question is the whole thesis in miniature: permission is granted to a name, not to an address. Because the protection system, too, sees names rather than bytes.

These questions do not belong to SQL, because they belong to the act of naming itself:

QuestionSQLMongoDBPOSIX file systemKafkaAmazon S3
Defining names (DDL)CREATE TABLEcreateCollectionmkdir, creatcreating a topiccreating a bucket
Changing (DML)INSERT/UPDATEinsertOnewrite, unlinkproducePutObject
Reading (DQL)SELECTfind, aggregateread, readdirconsume + offsetGetObject
Permission (DCL)GRANTgrantRolesToUserchmod, ACLtopic ACLIAM policy
Consistency (TCL)COMMITcommitTransactionfsync, journalidempotent producerper-object atomicity

SQL is merely the first widespread standard to stick academic labels on these questions. The layers are universal, because any program that names bytes and operates through those names must, willingly or not, have an answer for defining, changing, reading, authorising and keeping consistent — even if the answer is "hardly at all".

The epistemic status of this section. The historical evidence in section 1 is solid: the CODASYL origin of the DDL/DML terms is documented, and the standard's taxonomy is a matter of record. But as far as I know there is no canonical paper that explicitly declares the five an "anatomy of universal data languages". The generalisation here is a theorising of de facto practice: the industry does this (Cassandra's DDL/DML sections, MongoDB's transaction API, Kafka's ACLs) but rarely names it as such.

4. Boundary violations: the empirical evidence

Once the foundation is laid this way, why the system categories cannot be sharp follows by itself: if a file system, a database and a message queue are naming programs of equal standing working on the same bytes, then the difference between them is not one of kind but of degree — the richness of the answers they give to the five questions.

This is an old argument in the data systems literature too. Stonebraker and Çetintemel's "One Size Fits All": An Idea Whose Time Has Come and Gone (ICDE 2005) argues that these categories are an engineering trade-off, not a law of nature. Martin Kleppmann's Turning the Database Inside-Out and Jay Kreps's The Log both work through explicitly how the log/queue/database distinction is a set of different views onto the same underlying structure — an ordered log of bytes. Kafka's own self-description as a "distributed commit log" comes straight from this line of thought.

Boundary violations are a constant reminder:

SystemIts labelThe violation
Transactional NTFSfile systemAdded full atomicity (question 5) to file operations — in the same transaction as the Registry and SQL. Microsoft now "strongly recommends" alternatives, citing the complexity and the low uptake.
ZFSfile systemThe DMU layer at the heart of its architecture is, by definition, a general-purpose transactional object store; the POSIX file system (ZPL) is only one view laid over it.
Btrfsfile systemBuilt directly on a database technique: shadowing (copy-on-write) B-trees and clones.
SQLitedatabaseA single file from outside; but by its own measurements it is 35% faster at reading and writing ~10 KB blobs than keeping them as separate files, and takes ~20% less space. Which is to say it does "the file system's job" better than the file system.
Kafkamessage queueWrites messages to disk, retains them indefinitely, replays them by offset, and lets you run SQL queries over them. "Is Kafka a database?" has been debated in earnest in the industry.
PostgreSQLdatabaseRun as a queue with LISTEN/NOTIFY and SKIP LOCKED. Postgres's own documentation explicitly recommends SKIP LOCKED for the multiple-consumer scenario on "queue-like tables".
WinFSfile systemMicrosoft's attempt (2003–2006) to build the file system directly on a relational database. Abandoned, but the intent was plain.
BeFSfile systemIndexed attributes and query support — DQL embedded in a file system in the nineties.

Look at it from the other end: pull transaction support out of a graph database, and what is left is a program that gives names to groups of bytes joined by pointers and promises no atomicity — functionally, a file system. Databases that behave like queues and queues that behave like databases exist at the same time — because they are all doing the same thing: putting names on bytes and producing answers to the five questions.

The question "is this still a file system, or a database with hierarchical names?" has no answer, because it is badly posed. What changes is not the kind of system but the strength of its answer to the fifth question.

5. Ideal poles and a spectrum

Rather than throwing the categories out altogether, we can use them the way physics uses the ideal gas: poles that do not exist in reality but that serve to measure what does. The counterpart in the social sciences is Max Weber's notion of the ideal type (Idealtypus) — a pure form constructed not to describe but as a yardstick for comparison.

Real systems sit inside the surface these three corners span.

maximum namingTHE IDEAL DATABASETHE IDEAL FILE SYSTEMminimum namingTHE IDEAL MESSAGE QUEUEtemporal namingPostgreSQLMongoDBSQLiteRedisKafkaRabbitMQZFS · Btrfsext4S3Colour = the label the system gives itself:file systemdatabasemessage queue
Colour shows the system's label, position its behaviour; every place the two disagree is a boundary violation. The placements are qualitative and open to argument.

SQLite leans from the DB corner towards the FS corner: a single file from outside, a full universe of names from within. ZFS reaches its consistency arm from the FS corner towards DB. Kafka has travelled a fair way from the MQ corner towards DB. Redis wanders in the middle of all three.

No real system sits exactly on a corner; the ones that try usually turn out useless, because real workloads are not pure. That was precisely Stonebraker's argument.

6. The five questions as a measuring instrument

The real value of the five layers lies in using them not as a taxonomy but as a measuring instrument. How deep is a system's name scheme (DDL), how rich its algebra over names (DQL), how strict its consistency promise (TCL) — these answers give the system's coordinates on the spectrum far more reliably than its marketing label does.

none / best effortserialisable transactionsConsistency promise (TCL) →an opaque block of bytesnames at cell level + algebraNaming depth (DDL + DQL) →ext4S3RabbitMQZFS · BtrfsKafkaRedisMongoDBSQLitePostgreSQLfile systemdatabasemessage queue
The labels (colour) form no clean clusters along the axes: ZFS, a “file system”, promises stronger consistency than Redis, and Kafka, a “queue”, names more deeply than RabbitMQ. The placements are qualitative and open to argument.

"Is this a database?" thereby stops being a yes/no question and turns into this:

How deeply does it name the bytes, and what does it promise those names?

In practice you can use this as a checklist:

QuestionWhat to look forWeak endStrong end
DDLdepth of the name schemea single level, untyped namesnested, typed, constrained schema
DMLgranularity of a changereplace or delete the whole thingpartial update at field level
DQLpower of the name algebrafetch by exact namefiltering, joining, aggregation
DCLresolution of permissionsall-or-nothingpolicy at row/column level
TCLstrictness of the promisebest effortmulti-object serialisable transactions

7. Objections and limits

This framework does not explain everything; if it claimed more than it explains it would be wrong.

  1. The risk of reductionism. "It's all naming bytes" is true but insufficient. A system's performance characteristics — access patterns, index structure, cache behaviour, the cost of durability — cannot be derived from the answers to the five questions. The difference between a B-tree and an LSM-tree is invisible in this framework, and in production it determines everything.
  2. The distributed dimension is missing. The five questions assume a single node. Replication, partitioning and the CAP trade-offs are a separate axis; the "TCL" heading is not broad enough to carry them.
  3. We are not saying the categories are useless. The word "database" is a useful shorthand pointing at a region of the spectrum. The problem is not the word itself but its being mistaken for a natural kind.
  4. Section 3 has a different status. The universality of the five questions is defended here by induction, not by a historical document. It may be possible to find a counterexample — and if one is found, the framework should be corrected.

8. Practical value

This three-storey view — the byte is what is real, names are interpretation, categories are a spectrum — has concrete returns.

First, it produces transferable knowledge. Someone who has grasped the five questions knows what to look for when they open the documentation of a system they have never seen: what names does it give the bytes, how does it change and read those names, who may touch them, what does it promise. Whatever the system calls itself, the questions are the same.

Second, it frees the mind during debugging and data recovery. In the byte view, "the file is corrupted" means "the naming program can no longer interpret these bytes" — the bytes are still there. Opening a corrupted SQLite file in a hex editor and pulling the rows out by hand, or recovering a deleted file by reading the disk raw, comes naturally only to someone who knows that the names are interpretation and the bytes are real.

Third, it frees system selection from labels. "We need a message queue" is an incomplete sentence; what it should say is "we need a point that names bytes to this depth, retains them for this long, and gives this delivery guarantee". Once that description is made, it becomes visible that the answer need not come from a product labelled MQ — that perhaps the PostgreSQL you already have, with SKIP LOCKED, already sits at that point.

Fourth, it is a design guide. If you are designing your own data layer, the job is clear: dress the bytes in a naming scheme and give conscious answers to the five questions. Writing down from the outset which corner you will sit near and which question you will deliberately answer weakly lets you own being "a bit of this and a bit of that" as a design decision rather than a defect.

9. Conclusion

Taking DDL, DML, DQL, DCL and TCL for sublanguages of SQL is like taking the alphabet for an invention of the English language — and the historical evidence here is clear-cut: the terms were born in 1971, three years before SQL, for a different data model.

But the chain of corrections doesn't end there. The layers belong not to SQL but to the act of naming itself. The categories are not a law of nature but lines drawn across a spectrum. And the work every system on that spectrum does is, at bottom, one and the same: giving a name to a group of bytes at known addresses, and producing answers to five questions through those names.

File, row, document, message — all of them are in the eye of the program doing the looking. None of them are on the disk.

On a disk there are only bytes; and the byte is what is real.


References

Foundational texts

  1. Codd, E. F. (1970). A Relational Model of Data for Large Shared Data Banks. CACM 13(6), 377–387. doi:10.1145/362384.362685
  2. CODASYL Data Base Task Group (1971). April 1971 Report — the source of the DDL/DML terms and of the schema/subschema concepts. Overview · ACM reprint
  3. Chamberlin, D. D. & Boyce, R. F. (1974). SEQUEL: A Structured English Query Language. SIGFIDET '74. doi:10.1145/800296.811515
  4. ANSI/X3/SPARC Study Group on DBMS (1975). Interim Report — the three-schema architecture. Overview
  5. ISO/IEC 9075-2:2016, Database languages — SQL — Part 2: Foundation. ISO entry · the standard's 16 parts

Naming, files and abstraction

  1. Ritchie, D. M. & Thompson, K. (1974). The UNIX Time-Sharing System. CACM 17(7). doi:10.1145/361011.361061
  2. Saltzer, J. H. (1978). Naming and Binding of Objects. LNCS 60. PDF
  3. Pike, R. et al. (1993). The Use of Name Spaces in Plan 9. Text
  4. Soltis, F. — IBM System/38 and single-level store. Biography · System/38's embedded database

Transactions and protection

  1. Gray, J. (1981). The Transaction Concept: Virtues and Limitations. Tandem TR 81.3. PDF
  2. Saltzer, J. H. & Schroeder, M. D. (1975). The Protection of Information in Computer Systems. Proc. IEEE 63(9). Text

The blurring of boundaries

  1. Stonebraker, M. & Çetintemel, U. (2005). “One Size Fits All”: An Idea Whose Time Has Come and Gone. ICDE 2005. PDF
  2. Kreps, J. (2013). The Log. LinkedIn Engineering
  3. Kleppmann, M. (2015). Turning the Database Inside-Out. Confluent
  4. Kleppmann, M. (2018). Is Kafka a Database? Kafka Summit SF. Talk notes
  5. Rodeh, O. (2008). B-trees, shadowing, and clones. ACM TOS 3(4). doi:10.1145/1326542.1326544
  6. Rodeh, O., Bacik, J. & Mason, C. (2013). BTRFS: The Linux B-Tree Filesystem. ACM TOS 9(3). doi:10.1145/2501620.2501623
  7. Bonwick, J. (2007). ZFS: Rampant Layering Violation? Archived copy
  8. Giampaolo, D. (1999). Practical File System Design with the Be File System. PDF

Product documentation

  1. Microsoft. Alternatives to using Transactional NTFS. MS Learn
  2. SQLite. 35% Faster Than The Filesystem · SQLite As An Application File Format
  3. PostgreSQL. SELECT — The Locking Clause · NOTIFY
  4. Apache Cassandra. Data Definition · Data Manipulation
  5. Oracle. Deprecated and Desupported Features for Oracle Database 12c
  6. Microsoft. WinFS
  7. Weber, M. — ideal type (Idealtypus)