Posts Tagged “database”

Let’s have the database models strut down the runway:

Relational (SQL):

  • Data consist of rows in tables.
  • Each row has multiple columns.
  • Each column has a fixed type.
  • Queries use filters and joins.
  • Fixed schema is defined separately from the data.
  • User-defined indexes improve query performance.
  • Robust transaction/data-integrity support.

Graph (RDF):

  • Data consist of nodes and labeled links between them.
  • Nodes may have type information.
  • Optional schema is defined in the same model (e.g. RDFS, OWL).
  • Queries use graph-based constraints and filters.
  • Indexes are not optimized for specific datasets.
  • Limited transaction support.

Tree (XML, filesystem):

  • Data are identified by a name and a position within a hierarchy.
  • Queries use hierarchies and filters.
  • Data may have type information.
  • Optional schema may be defined in the same model (XML-Schema) or outside it (DTD).
  • Transaction support varies by implementation.

Hash (BDB, memcached):

  • Data are untyped binary blobs.
  • Data are identified by unique keys in a flat namespace.
  • Only key-based lookups are possible.
  • Limited transaction support.

Inverted Index (Lucene/Solr):

  • Data are text documents.
  • Queries are free-form text with some special operators.
  • Text queries are fast.
  • Query results can be scored/ranked.
  • Joins are inefficient; denormalized data are preferred.
  • Limited transaction support.

Document-Oriented (CouchDB):

  • Data are identified by unique keys in a flat namespace.
  • Data have named fields.
  • Optional schema defined by application code.
  • Denormalized data are preferred.
  • Limited type information.

Column-Oriented (Hbase, BigTable):

  • Data consist of rows in tables.
  • Each row has multiple columns, rows are assumed to be sparse.
  • Data from a single column are stored contiguously to improve performance.
  • Designed for distributed processing environments such as Hadoop and MapReduce.

Comments No Comments »

Since I started working on AltLaw.org a little over a year ago, I’ve struggled with the data model. I’ve got around half a million documents, totally unstructured, from a dozen different sources. Each source has its own quirks and problems that have to be corrected before it’s useful.

When I started, I was using MySQL + the filesystem + Ferret. Keeping all that in sync, even with Rails’ ActiveRecord, was tricky, and searches were slow. Now I’ve got everything stored directly in a Solr index, which is very fast for searching. But it’s not so great when I want to change, say, how I convert the source PDFs into HTML, and I have to re-index half a million documents. And it can’t store structured data very well, so I augment it with serialized hash tables and SQLite.

What I want is a storage engine that combines properties of a relational database and a full-text search engine. It would put structured fields into SQL-like tables and unstructured fields into an inverted index for text searches. I want to be able to do queries that combine structured and unstructured data, like “cases decided in the Second Circuit between 1990 and 2000 that cite Sony v. Universal and contain the phrase ‘fair use’.” I also want to store metadata about my metadata, like where it came from, how accurate I think it is, etc.

I’ve been exploring some interesting alternatives: CouchDB is probably the closest to what I want, but it’s still under heavy development. DSpace is oriented more towards archival than search. Then there’s the big RDF monster, maybe the most flexible data model ever, which makes it correspondingly difficult to grasp.

I’m come to the conclusion that there is no perfect data model. Or, to put it another way, no storage engine is going to do my work for me. What I need to do is come up with a solid, flexible API that provides just the features I need, then put that API in front of one or more back-ends (Lucene, SQL, the filesystem) that handle whatever they’re best at.

Comments 3 Comments »