Web developers already have localStorage, which is used for client side storage of simple key-value pairs. This alone doesn’t address the needs of many web applications for structured storage and indexed data. Mozilla is working on a structured storage API with indexing support called IndexedDB, and we will have some test builds in the next few weeks. This can be compared to the WebDatabase API implemented by several browsers that uses a subset of the allowable language of SQLite. Mozilla has chosen to not implement WebDatabase for various reasons discussed in this post.

In order to compare IndexedDB and WebDatabase, we are going to show four examples that use most parts of the asynchronous APIs of each specification. The differences between SQL storage with tables (WebDatabase) and JavaScript object storage with indexes (IndexedDB) becomes pretty clear after reading the examples. The synchronous versions of these APIs are only available on worker threads. Since not all browsers currently implement worker threads, the synchronous APIs will not be discussed at this time. The IndexedDB code is based off a proposal that Mozilla has submitted to the W3C WebApps working group that has gotten positive feedback so far. The code for both APIs does not include any error handling (for brevity), but production code should always have it!

These examples are for the storage of a candy store’s sale of candy to customers, which we’ll refer to as kids. Each entry in candySales represents a sale of a specified amount of candy to a kid, specified by an entry in candy and kids respectively.

Example 1 – Opening and Setting Up a Database

This first example demonstrates how to open a database connection and create the tables or object stores if the version number is not correct. Upon opening the database, both examples check the version and create the necessary tables or object stores and then set the correct version number. WebDatabase is a bit stricter in how it handles versions by giving an error if the database version is not what the caller expects (this is specified by the second argument to openDatabase). IndexedDB simply lets the caller handle versioning as they see fit. Note that there is active discussion about how IndexedDB should handle version changes in the working group.

WebDatabase

var db = window.openDatabase("CandyDB", "",
                             "My candy store database",
                             1024);
if (db.version != "1") {
  db.changeVersion(db.version, "1", function(tx) {
    // User's first visit.  Initialize database.
    var tables = [
      { name: "kids", columns: ["id INTEGER PRIMARY KEY",
                                "name TEXT"]},
      { name: "candy", columns: ["id INTEGER PRIMARY KEY",
                                 "name TEXT"]},
      { name: "candySales", columns: ["kidId INTEGER",
                                      "candyId INTEGER",
                                      "date TEXT"]}
    ];
 
    for (var index = 0; index < tables.length; index++) {
      var table = tables[index];
      tx.executeSql("CREATE TABLE " + table.name + "(" +
                    table.columns.join(", ") + ");");
    }
  }, null, function() { loadData(db); });
}
else {
  // User has been here before, no initialization required.
  loadData(db);
}

IndexedDB

var request = window.indexedDB.open("CandyDB",
                                    "My candy store database");
request.onsuccess = function(event) {
  var db = event.result;
  if (db.version != "1") {
    // User's first visit, initialize database.
    var createdObjectStoreCount = 0;
    var objectStores = [
      { name: "kids", keyPath: "id", autoIncrement: true },
      { name: "candy", keyPath: "id", autoIncrement: true },
      { name: "candySales", keyPath: "", autoIncrement: true }
    ];
 
    function objectStoreCreated(event) {
      if (++createdObjectStoreCount == objectStores.length) {
        db.setVersion("1").onsuccess = function(event) {
          loadData(db);
        };
      }
    }
 
    for (var index = 0; index < objectStores.length; index++) {
      var params = objectStores[index];
      request = db.createObjectStore(params.name, params.keyPath,
                                     params.autoIncrement);
      request.onsuccess = objectStoreCreated;
    }
  }
  else {
    // User has been here before, no initialization required.
    loadData(db);
  }
};

Example 2 – Storing Kids in the Database

This example stores several kids into the appropriate table or object store. This example demonstrates one of the risks that have to be dealt with when using WebDatabase: SQL injection attacks. In WebDatabase explicit transactions must be used, but in IndexedDB a transaction is provided automatically if only one object store is accessed. Transaction locking is per-object store in IndexedDB. Additionally, IndexedDB takes a JavaScript object to insert, whereas with WebDatabase callers must bind specific columns. In both cases you get the insertion id in the callback.

WebDatabase

var kids = [
  { name: "Anna" },
  { name: "Betty" },
  { name: "Christine" }
];
 
var db = window.openDatabase("CandyDB", "1",
                             "My candy store database",
                             1024);
db.transaction(function(tx) {
  for (var index = 0; index < kids.length; index++) {
    var kid = kids[index];
    tx.executeSql("INSERT INTO kids (name) VALUES (:name);", [kid],
                  function(tx, results) {
      document.getElementById("display").textContent =
          "Saved record for " + kid.name +
          " with id " + results.insertId;
    });
  }
});

IndexedDB

var kids = [
  { name: "Anna" },
  { name: "Betty" },
  { name: "Christine" }
];
 
var request = window.indexedDB.open("CandyDB",
                                    "My candy store database");
request.onsuccess = function(event) {
  var objectStore = event.result.objectStore("kids");
  for (var index = 0; index < kids.length; index++) {
    var kid = kids[index];
    objectStore.add(kid).onsuccess = function(event) {
      document.getElementById("display").textContent =
        "Saved record for " + kid.name + " with id " + event.result;
    };
  }
};

Example 3 – List All Kids

This example lists all of the kids stored in the kids table or the kids object store. WebDatabase uses a result set object which will be passed to the callback method provided after all rows have been retrieved. IndexedDB, on the other hand, passes a cursor to the event handler as results are retrieved. Results should come back faster, as a result. While not shown in this example, you can also stop iterating data with IndexedDB by simply not calling cursor.continue().

WebDatabase

var db = window.openDatabase("CandyDB", "1",
                             "My candy store database",
                             1024);
db.readTransaction(function(tx) {
  // Enumerate the entire table.
  tx.executeSql("SELECT * FROM kids", function(tx, results) {
    var rows = results.rows;
    for (var index = 0; index < rows.length; index++) {
      var item = rows.item(index);
      var element = document.createElement("div");
      element.textContent = item.name;
      document.getElementById("kidList").appendChild(element);
    }
  });
});

IndexedDB

var request = window.indexedDB.open("CandyDB",
                                    "My candy store database");
request.onsuccess = function(event) {
  // Enumerate the entire object store.
  request = event.result.objectStore("kids").openCursor();
  request.onsuccess = function(event) {
    var cursor = event.result;
    // If cursor is null then we've completed the enumeration.
    if (!cursor) {
      return;
    }
    var element = document.createElement("div");
    element.textContent = cursor.value.name;
    document.getElementById("kidList").appendChild(element);
    cursor.continue();
  };
};

Example 4 – List Kids Who Bought Candy

This example lists all the kids, and how much candy each kid purchased. WebDatabase simply uses a LEFT JOIN query which makes this example very simple. IndexedDB does not currently have an API specified for doing a join between different object stores. As a result, the example opens a cursor to the kids object store and an object cursor on the kidId index on the candySales object store and performs the join manually.

WebDatabase

var db = window.openDatabase("CandyDB", "1",
                             "My candy store database",
                             1024);
db.readTransaction(function(tx) {
  tx.executeSql("SELECT name, COUNT(candySales.kidId) " +
                "FROM kids " +
                "LEFT JOIN candySales " +
                "ON kids.id = candySales.kidId " +
                "GROUP BY kids.id;",
                function(tx, results) {
    var display = document.getElementById("purchaseList");
    var rows = results.rows;
    for (var index = 0; index < rows.length; index++) {
      var item = rows.item(index);
      display.textContent += ", " + item.name + "bought " +
                             item.count + "pieces";
    }
  });
});

IndexedDB

candyEaters = [];
function displayCandyEaters(event) {
  var display = document.getElementById("purchaseList");
  for (var i in candyEaters) {
    display.textContent += ", " + candyEaters[i].name + "bought " +
                           candyEaters[i].count + "pieces";
  }
};
 
var request = window.indexedDB.open("CandyDB",
                                    "My candy store database");
request.onsuccess = function(event) {
  var db = event.result;
  var transaction = db.transaction(["kids", "candySales"]);
  transaction.oncomplete = displayCandyEaters;
 
  var kidCursor;
  var saleCursor;
  var salesLoaded = false;
  var count;
 
  var kidsStore = transaction.objectStore("kids");
  kidsStore.openCursor().onsuccess = function(event) {
    kidCursor = event.result;
    count = 0;
    attemptWalk();
  }
  var salesStore = transaction.objectStore("candySales");
  var kidIndex = salesStore.index("kidId");
  kidIndex.openObjectCursor().onsuccess = function(event) {
    saleCursor = event.result;
    salesLoaded = true;
    attemptWalk();
  }
  function attemptWalk() {
    if (!kidCursor || !salesLoaded)
      return;
 
    if (saleCursor && kidCursor.value.id == saleCursor.kidId) {
      count++;
      saleCursor.continue();
    }
    else {
      candyEaters.push({ name: kidCursor.value.name, count: count });
      kidCursor.continue();
    }
  }
}

IndexedDB generally simplifies the programming model for interacting with databases, and allows for a wide number of use cases. The working group is designing this API so it could be wrapped by JavaScript libraries; for instance, there’s plenty of room for a CouchDB-style API on top of our IndexedDB implementation. It would also be very possible to build a SQL-based API on top of IndexedDB (such as WebDatabase). Mozilla is eager to get developer feedback about IndexedDB, particularly since the specification has not been finalized yet. Feel free to leave a comment here expressing your thoughts or leave anonymous feedback through Rypple.

168 comments

Post a comment
  1. Morn wrote on December 6th, 2010 at 1:48 am:

    I don’t know why that firefox 4.0b7 changed the indexedDB API,I made a demo before,and it works all nice in beta 2,but now it totally can’t work in beta 7.do you know anything about the method of indexedDB.open() ?

    Reply

  2. Chad wrote on December 11th, 2010 at 5:04 pm:

    Anyone know of vacuum sql cleaner alternative for Firefox 4 B7?

    Reply

  3. Jesse Morgan wrote on December 12th, 2010 at 4:02 am:

    Hey guys, some interesting discussion going on in here.

    I think the way Mozilla are heading is correct. If we don’t get this right now, before web-application’s begin to supplant client-side apps, we’re just going to be in one whole kludge of a mess that can’t be undone easily.

    Look at the trouble a single short-sighted product design has inflicted on the technological growth of the internet by not thinking of the long term implications. I’m talking about internet explorer.

    While the guy several posts up with broken English was a little hard to understand, I agree that the well established model of thinking of data in terms of tables and columns is an overly restrictive and case-specific thing to force on the web as a lowest common denominator. More loosely defined object stores just make more sense here and as has been stated, more rigid table-like semantics can be implemented on top of this if required.

    I do think that we definitely need a clear and concise syntax for querying these object stores. Again this, as stated, makes sense as a higher level implementation..

    In terms of a simple, flexible, but structured and finitely defined querying approach, I can’t help but think of Microsoft’s LINQ – Or more specifically, The whole IEnumerable interface and accompanying LINQ methods.

    To be clear for those who know LINQ, the object methods required to support LINQ querying are distinct from it’s SQL-like query syntax, which just compiles down to methods on return objects. You can still use LINQ without writing a string based query.

    A quick google turns up a couple of Javascript implementations of this!, which excites me a little if only to have a play.

    http://linqjs.codeplex.com/
    http://jsinq.codeplex.com/

    Examples:
    var result =
    customers.groupBy(function(customer) {
    return customer.lastname;
    }).
    select(function(g) {
    return {lastname: g.key, count: g.count()};
    }).
    orderByDescending(function(r) {
    return r.count;
    });

    var query = new jsinq.Query(‘\
    from customer in $0 \
    group customer by customer.lastname into g \
    select {lastname: g.key, count: g.count()} \
    into r \
    orderby r.count descending \
    select r \
    ‘);

    query.setValue(0, customers);
    var result = query.execute();

    Also an obligatory ‘JOIN’ example.
    from order in $2
    join product in $1 on order.product equals product.id
    select {customer: order.customer, price: product.price}
    into p
    group p by p.customer
    into g
    select {customer: g.getKey(), sum: g.sum(function(q) { return q.price; })}
    into c
    join customer in $0 on c.customer equals customer.id
    orderby c.sum descending
    select {name: customer.firstname + ‘ ‘ + customer.lastname, ‘sum of all purchases’: ‘$’ + c.sum}

    Because JS is a prototype based language, supporting the querying methods on enumerable objects (just arrays??) should be fairly easy to complete in full. This looks like the case with the links I posted.

    Where the real guts would come in is the more lower level interaction between it and DBIndex, so that data iteration can happen lazily. But I’m sure it could be done!

    Reply

  4. Paul wrote on December 27th, 2010 at 10:29 pm:

    As a web developer, the solution is simple from my perspective. Drop firefox support in my apps as so many did in the prior browser war, and handle IE users with Chrome Frame. This is really fairly simple since firefox is still a minority browser.

    No offense to mozilla but I really have no intention of holding off on using key technologies that work in favor of someone else’s political games.

    To me it would be better to declare support for SQL92 or draft a new SQL-like spec. If current implementations don’t comply, then it should be considered a bug.

    Reply

    1. Chris wrote on June 2nd, 2011 at 2:52 pm:

      “This is really fairly simple since firefox is still a minority browser.”

      Hogwash. As of April 2011, FF had a 42.9% market share. The next largest share was Chrome at 26.5%.

      Reply

      1. Chris wrote on August 29th, 2011 at 2:28 am:

        Dude,
        Do not use w3schools.com for web stats, although it doesn’t explicitly state it on their site I am convinced that the stats come from users of their site, so their stats have some considerable sample bias – quite simply web developers, and aspiring web developers are more likely to use FF or Chrome.
        If you found some better, more representative, stats you’d probably find IE is still leading (it is the default option on Windows, and not that many will change), followed by FF, and then Chrome. Opera, Safari and Rockmelt might have a percent or two each.

        Reply

  5. Clay Lenhart wrote on January 4th, 2011 at 3:32 pm:

    C# has benefited from LINQ, and there’s no reason Javascript can’t enjoy this as well. In short the answer is to modify the Javascript language to support querying.

    Take a look at the Pig script here (http://www.readwriteweb.com/cloud/2011/01/how-twitter-uses-nosql.php). The Pig script is completely understandable. You could easily see a Pig language embedded in Javascript like LINQ is embedded in C#.

    Reply

  6. John wrote on January 14th, 2011 at 8:20 am:

    @Paul, I can’t believe you consider yourself a web developer yet you would drop one of the fastest advancing and most popular web browsers to date.

    The majority of mobile users are using webkit now (iOS and Android), which Firefox complies with almost entirely. I find very few things that don’t work among the most popular browsers: Chrome, Safari, and Firefox.

    Firefox 4 is offering some amazing new technology that will push online applications and gaming into the next generation. Other browsers will follow suit, so if you expect to have a job as a web dev I highly recommend not dropping support for Firefox in your apps.

    Reply

    1. Paul wrote on January 15th, 2011 at 9:32 am:

      To be clear I’m not talking about dropping support for firefox alltogether, but for apps that would use offline storage.

      I really have trouble seeing how stuffing a whole new query language into javascript will be anything but painful for someone who needs to deal with more than 3 or 4 “tables”. Especially considering that this solution has us going back to walking through btrees.

      WebDB is an existing standard in production-level browsers. Offline apps can be developed against it without having to support / keep up with an experimental standard used exclusively in experimental versions of browsers.

      There’s no way I’d be able to keep my job as a web developer if I had to try and justify developing anything against this.

      Reply

      1. Shawn Wilsher wrote on January 18th, 2011 at 3:10 pm:

        The problem with WebDB is that it never reached CR status, and is in fact considered a deprecated standard now.

        Reply

  7. codeguru413 wrote on February 1st, 2011 at 10:06 am:

    I for one am not a fan of this IndexedDB thing….yet. For one, I am comfortable with tables and database terms. However, that is not a good enough reason to say we should use that style of storage access and development. There is something to be said about using the notion of “objects”, as that’s what we deal with in our everyday physical lives, and so is a good analogy in terms of computing and storage. What I didn’t see from the examples above, is more complicated relational logic…which is important for, well, relating objects to one another. Now, perhaps the examples above are overly simplistic in an attempt to only demonstrate IndexedDB and contrast it with the proposed WebDatabase proposal (which admittedly, is severly flawed in that as of right now, it primarily deals with SQLite).

    But, before we go jumping on the Indexed DB bandwagon, let’s consider one alternative that could make WebDatabase work (or, even enhance IndexedDB in terms of using a object-relational model instead of a tabular-relational model–which if you think about it, isn’t really all that different when you consider that at the core, it’s all relational algebra). Anyway, the main problem is that the databases (e.g. MS SQL Server (or CompactSQL), SQLLite, etc.) al use a different “dialect” of SQL–to put it mildly. Since most of these “compact” and lite databases are offered for free, there really isn’t any reason why they each need to speak a different dialect of SQL. Perhaps there should be a single standard of SQL used for the Web only that all these different compact databases will use (or database engines created specifically for WebDatabase or IndexedDB) in order to facilitate cross-browser, cross-DB support? I know, seems novel…. I don’t understand why we can’t all get over ourselves and make this happen.

    Anyway, just my $0.02… You don’t have to get mad at me. If you don’t like what I say, just move on and read something else or continue to do whatever you do currently.

    Mostly, I just encourage everyone who’s making an effort to bring this to fruition to make the interface as simple as possible to query. Data is king, and many people without formal knowledge of database technology need to query and analyze that data–even creating “queries” on the fly.

    Reply

  8. Rafal wrote on February 14th, 2011 at 12:57 am:

    Are you able to run example codes from this post in Firefox 4 beta 10 or 11?
    My problem is that the success event triggered after calling mozIndexedDB.open() doesn’t have result property and I cannot get to the instance of the database? Is this a firefox bug or am I doing something wrong?

    Reply

  9. Rafal wrote on February 14th, 2011 at 2:18 pm:

    OK, I found the answer myself. In Firefox you have to read the result from the request object not the event object. Don’t understand why it is done that way, cause the Indexed DB draft says something else.

    Reply

  10. Ben Dilts wrote on March 2nd, 2011 at 12:09 am:

    Those code samples read like advertisements for Web SQL. In every case, I would pay money to be allowed to use the Web SQL code rather than the Indexed DB code.

    I just tried implementing a simple one-table, one-index setup in Firefox 4 using IndexedDB, and the code is so painful to write, and the performance so dismal (4 *seconds* to simply loop through 200 objects of about 1KB each with a cursor) that I’m ready to support *anything* other than this.

    Reply

  11. ray wrote on March 7th, 2011 at 9:46 pm:

    I believe the code examples speak for themselves. Every example with the exception of “Storing Kids…” is longer as IndexDB. How is this helpful?

    Reply

    1. Paul wrote on March 7th, 2011 at 10:46 pm:

      For that matter – what exactly about looping through objects for child relationships is indexed?

      Reply

  12. Mike Wilson wrote on March 21st, 2011 at 9:56 pm:

    Just my 2 cents here but why didn’t Mozilla simply support WebDB as originally specified by WC3? Seriously? You have to write your own join strategies? It’s 2011, but Mozilla has implemented a storage strategy that basically throws away about 40 years of grounded relational theory (Codd, et al)? Even if you don’t like the proprietary(-ish) nature of Sqlite couldn’t they have come up with something that at least had SQL join syntax?

    Grrrr. I’m currently doing a HTML5 audit of features for a new product I’m writing and because of this I’m seriously thinking about excluding Firefox as a supported browser. Go Chrome!

    Reply

    1. Christopher Blizzard wrote on March 22nd, 2011 at 9:58 am:

      Chrome is also likely to support IndexedDB.

      Reply

      1. Greg wrote on March 22nd, 2011 at 10:13 am:

        Hopefully Mozilla will follow Chrome’s lead and support both storage technologies :)

        Reply

        1. Shawn Wilsher wrote on March 22nd, 2011 at 10:19 am:

          Why would Mozilla implement a specification that has been marked as deprecated?

          Reply

          1. Marcelo Cantos wrote on March 23rd, 2011 at 4:15 am:

            You guys have a major influence on these standards. Complaining that it’s deprecated is just a cop-out. Why can’t you just pick up the standard in whatever state it’s in, and fix whatever issues it has? You moan about the fact that the standard references a specific implementation and the consequent difficulties of defining the language independently of one, but most of the work has already been done for you. SQLite supports most of the SQL-92 syntax. So, as a starting point, Web SQL Database could define a subset of SQL-92 that happens to also be a subset of SQLite syntax.

            Now, I’m not totally naïve. I’m sure it’s more complicated than that, but do you seriously expect us to believe that it would be more work than what you’re trying to do now?

  13. John Smith wrote on April 4th, 2011 at 10:03 pm:

    Yes, the decision is pretty bad.
    Yes, the excuses are laughable.
    OK, let’s think for a minute.
    Please correct me if I am wrong, but there should be some rationale behind this.
    People at Mozilla are not idiots and morons (as per Kevin Layman).
    So, who benefits most from hindering acceptance of common browser SQL DB standard?
    Obviously, the company who owns the desktop.
    Who loses most?
    Obviously, the company who wants to move all apps to the net.
    Is it counter intuitive that Mozilla took the side of the former, rather than the later?
    Yes, it is, but we do not know everything behind the scenes.
    Is it possible that some money changed hands or someone was offered high position at Microshaft?
    Who knows?

    Anyway, what would be the consequences?
    Shall businesses start to move to webkit based browsers their intranet apps?
    Shall Mozilla move be side steped with another Chrome frame?
    Shall some new, killer app, based on WebDatabase, pop up and swipe Mozilla market share?

    Thoughts?

    Reply

    1. Dan wrote on June 13th, 2011 at 8:16 am:

      “Yes, it is, but we do not know everything behind the scenes.
      Is it possible that some money changed hands or someone was offered high position at Microshaft?”

      @John Smith – You’re kidding me right buddy? Mozilla is a 501.3C NPO, so the idea that the new IndexedDB standard came about through some clandestine database hush-money conspiracy is laughable.

      “Can I get a price check on tin-foil for checkstand 8, we have a gentleman here who needs a large quantity, apparently he’s making hats.”

      Reply

  14. Jesse Morgan wrote on April 7th, 2011 at 5:41 pm:

    The people screaming for SQL to be supported – SQL is horribly prehistoric. It’s 2011! We can do better, and why should be support older syntax at the expense of progress.

    I commented previously on a LINQ-like syntax for indexdb – something that I think would work excellently for object store or noSQL style storage.

    Seems Microsoft Research agrees with me (not that I place faith in MS research – but the article is sound)
    http://queue.acm.org/detail.cfm?id=1961297

    Reply

    1. Paul wrote on April 8th, 2011 at 5:31 pm:

      It’s not a step forward until new capabilities are introduced.

      As I understand it, LINQ is an abstraction layer for SQL (there are even built-in utilities for viewing the SQL queries that are generated by LINQ). And while the syntax for LINQ is somewhat different, there are very few features that exist in SQL that cannot be found in LINQ.

      This is clearly not the case with indexedDB, there is no concept of relationship between data entities, you must maintain that yourself. Regardless of what year it is, looping through lists of objects to filter them on your own is not only more work syntactically, but it more work computationally.

      Any developer who’s been in the industry for more than a year or two should know by now that syntax is largely irrelevant as long as functionality is still there. I’m not married to the SQL language, i’m sure there are other methods for querying that are easier to read/maintain. But if we’re going to have an object relational model for persistent storage, then relational integrity must be guaranteed. This isn’t in indexedDB and until it is, it is an inferior standard when compared to webDB.

      So while it may be a good start, I have trouble justifying the time and effort to build against it when I can use Chrome and Chrome Frame and end up with a stable, maintainable application.

      Reply

      1. Jesse Morgan wrote on April 11th, 2011 at 6:36 pm:

        I don’t believe your understanding of LINQ is correct.

        LINQ is based on the IEnumerable interface. The concept is that any object that can be enumerated conforms to a single interface standard which can be operated on, queried and related using a unified model and syntax – with results being generated as implicit runtime types (js takes care of this by being prototype).
        There are no pre-existing relations. LINQ is definitely not a SQL generator. LINQ to SQL is a LINQ implementation for querying SQL. Likewise LINQ to Object or LINQ to XML perform the same for other data store types.

        The .NET Entity framework does exist to provide preset relations between objects, and it does integrate with LINQ but is not required. I believe this is where you are getting confused.

        Reply

      2. Jesse Morgan wrote on April 11th, 2011 at 6:42 pm:

        Also, iterating result sets is not implicitly more computationally expensive. I’m and not sure what would give you this idea?

        Regardless of whether the API you are using does the iteration for you, or you do it yourself; it’s still being done somewhere.

        With the case of indexedDB you are given the lower level control to perform this yourself. As has been indicated – another API can be built utilising indexedDB providing this relational ‘integrity’ in a packaged way.

        This has development method has worked great for libraries like jquery

        Reply

        1. Paul wrote on April 23rd, 2011 at 9:09 am:

          This isn’t a government project.

          Point taken with LINQ, I had confused it with LINQ to SQL. But I have to say that if SQL databases loop through entire datasets, that’s considered a “full table scan” and is a sign that you at least need some indexes defined.

          I think that you’ve hit the nail on the head about why there’s so much opposition to indexedDB. It’s a lower-level data storage solution, which means we have to go back to the drawing board on query tools, reporting tools, analysis tools, etc.

          This isn’t a government project. I don’t think that it’s unreasonable to think that concurrent efforts are possible, in fact the web is made of a multitude of standards that serve the same purpose with different strengths and weaknesses, giving designers and architects choices on what’s best for each application.

          The software industry has seen countless iterations of fundamental changes like this, as new technologies mature, they take replace the older technologies as they offer advantages in real-world applications. Beyond a more javascript-like syntax there is no advantage to indexedDB in terms of new features.

          In fact it has fewer features than WebDB. The examples demonstrate that the programmers are on their own when it comes to joins. There are no demonstrations of aggregates, or protections from things like orphans.

          I personally have no problem with working with new technologies, I find it strange when people in this industry do. But I also don’t understand the obsession so many in this industry have with syntax. I’ve worked with a lot of technologies and frankly I find that syntax rarely makes a difference. I especially don’t see the attraction to a new syntax when demonstrations like these show that the new syntax will result in MORE WORK.

          I’m sure that indexedDB will eventually mature into something that provides advantages, or will be replaced with something that does. Until then I can’t justify supporting firefox in mobile applications when I have support for WebDB built into every other browser (including IE through Chrome Frame).

          Reply

          1. Jesse Morgan wrote on April 23rd, 2011 at 5:03 pm:

            Hi again,
            Thanks for the thought out reply.

            I just think that an object store model suits much more to a modern environment and what I hope is a coming age of ubiquity with web technologies. The fact that you can reference a store of like objects indexed by common properties is fairly powerful.

            It fits the bill for javascript because it preserves the type-fluidity of prototype.

            I think that if you’re trying to use an object store as a SQL store, then you are correct; its a long way around.

            The power comes when you realise that you are not constrained in your storage to a table schema. All you must do is ensure that you set a meaningful key or key-property on the store value; the rest is free form.

            Take for instance an object store named ‘Entity’
            Now, ‘Entity’ stores records for both people, and companies.

            Therefore when we store objects in this store, we ensure we assign a unique ‘EntityID’ as a key – but the VALUE has little similarity beyond the fact that it has a property named ‘Entity Type’ which is a hint for which other related properties to expect exist.

            We may index ‘Entity Type’ to speed up querying, but essentially you have a SQL ‘table’ which has differing columns based on need.

            In this context, a ‘Person’ record may have First Name, Last Name, Username, Password, History[], Friends[]

            The latter two being arrays of more objects or EntityIDs

            Personally I’m not a big believer of database level relational management. It just seems like a copout for bad coding of whatever is calling the SQL queries.

            Don’t get me wrong, that’s obviously a broad sweeping statement to make – But I think you are right in that a DB systems primary function is indexed, timely access of information. Relation management comes second IMO and in this case I’d be more than happy to manage that in a higher layer.

            There’s also the fact that SQL is essentially a glorified text store. Obviously we have numeric datatypes too, inclusive of date. You can store ‘blobs’, but they are dumb – the db engine cannot understand them.

            What I’m not totally clear on here is that IndexedDB will take a ‘Value’ in it’s key/value pair as a standard javascript style object with properties – and allow QUERYING on the objects properties.

            This is a major benefit given the time I spend serialising and deserialising data to text if I have to use a SQL DB

  15. Jesse Morgan wrote on April 11th, 2011 at 6:59 pm:

    Perhaps I should wait a minute before posting so I can combine replies;

    What we have here is a critical path in technology. There was an article recently positing that we only have the industry and reliance on expensive liquid rocket technology we have now due to a specific sequence of events including world war 2 and Hitlers fascination with the V2 rocket, and ensuing cold war and ICBM leap-frog development.

    The end result is industry and ‘standardised’ technology relating to liquid rocket propulsion which may not necessarily be the best solution – but which we are stuck with because of the expense of ‘starting again’ and the investment and resistance of change of experience in the field.

    This is equally true in this scenario. We are talking about the platform of the future here, so it makes sense to take stock of what technologies form the base.

    Reply

  16. Shiby wrote on May 24th, 2011 at 2:08 am:

    IndexedDb is not working for me .. the code was simple, but its throwing an error while trying to open the database. Error: uncaught exception: [Exception... \The operation failed for reasons unrelated to the database itself and not covered by any other error code.\ code: \1\ nsresult: x80660001 (NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR)\ location: \file:///D:/shiby/html5/IndexedDB/IndexedDbSampleFF.htm Line: 14\]

    Anyone got any idea?

    Reply

    1. louisremi wrote on May 24th, 2011 at 5:45 am:

      More details on the code you are using would be helpful.
      Louis-Rémi

      Reply

      1. Shiby wrote on May 24th, 2011 at 10:30 pm:

        Its the similar code as above. Still will paste mine here :

        var request = window.mozIndexedDB.open(“todos”);
        request.onsuccess = function(event) {
        var v = “1.0″;
        var db = request.result;
        };

        At the line where the open method is called, the exception occurs

        Reply

  17. Pingback from Dive Into HTML5:本地存储(续二) | DevBean's World on June 13th, 2011 at 10:05 pm:

    [...] 如果你曾经做过 SQL 数据库编程,就会发现这些概念都十分雷同。二者主要区别在于,对象存储没有结构化查询语言的概念。你不需要类似”SELECT * from USERS where ACTIVE = ‘Y’”这种语句。你需要做的是使用对象存储机制提供的函数,在名为 USERS 的数据库上打开一个游标,遍历所有记录,过滤掉不活动的用户,使用访问函数读取剩下记录的所有字段。An early walk-through of IndexedDB 是一篇关于 IndexedDB 如何工作的不错的教程,给出了关于 IndexedDB 和 Web SQL Database 的对比。 [...]

    Reply

  18. Bill Harten wrote on June 27th, 2011 at 1:15 pm:

    50X Faster? “I never said the data in [table] cells had to be atomic” — Ed Codd, father of the relational database, 1999 Very Large Database Conference in San Francisco. I went to the conference just to hear him say it.

    He was defending his invention and explaining why object stores are often 50X to 100X faster than comparable relational implementations. He explained how the industry went astray in the hands of the first relational DB implementors by recognizing nothing more complex than atomic values (strings, ints, floats, blobs, etc.) in the cells of a table.

    Codd’s relational algebra showed how a complex real-world information structure can be normalized (decomposed) into a set of 2-dimensional tables and later reconstituted via the relational operators project, select, and join. The problem is that reconstituting from many smaller atomic parts takes more work than storing the same information in fewer compound pieces. This is why modern object stores, XML databases, object-oriented and the old hierarchical databases like MUMPS and IMS (ancient but they got it right) handle complex data orders of magnitude faster than relational. The only thing that allowed the relational database to survive and thrive these past 40 years was accelerating hardware following Moore’s Law.

    Really? In 1984 I created both a relational and an XML-based (GEDCOM) object database for the LDS Church FamilySearch database, the largest genealogical database in the world at the time. (I know, XML didn’t exist yet). Both were implemented and deployed in production serving the same requirements. We did both at the same time out of group uncertainty. The relational version was carefully indexed and semi-normalized to optimize for performance. Notwithstanding, the XML/GEDCOM-based system was over 50X faster, not 50% but 50X! A whole family, its members, and details were stored in a single compressed physical chunk. Deployed on a lowly 1984 PC, it ran circles around our relational system on multi-million dollar mainframe. This was due to the real-world complexity of the data and the effects of breaking data up versus keeping them together. The mainframe ended up preparing data for deployment on CDs.

    Learnings? IndexedDB’s ability to store a complex object can potentially yield much greater performance, if implemented to advantage. Lack of join and traversal semantics, bulky syntax, and other problems have been solved before in other settings; we just need to put our heads, best ideas, and data together.

    Reply

  19. Paul wrote on June 30th, 2011 at 4:09 am:

    This seems a big backwards step to me.

    There is a reason SQL doesn’t just have a ‘SELECT * FROM mytable’ command (which is essentially what IndexedDB seems to have, as far as I can see).

    Anything that you can do in IndexedDB you can do with a similar level of difficulty in SQL, but things you can do easily in SQL look to be really complicated and/or inefficient in IndexedDB. Maybe there are some things which are easier in IndexedDB, but they’re not clear from these examples…

    Saying that disk I/O will be slow compared to Javascript reading and filtering data, for instance, is very disingenous. This ignores the fact of caching. Consider doing a sequential scan of a 50MB database. If the database has to be read from disk, the disk speed will make the difference between JS and a compiled language have very small effect on the overall time. However, if the database has been loaded into memory (either in the DB engine, or just in the OS cache), then the difference between JS and the compiled language will be MUCH more significant.

    Reply

    1. Bill Harten wrote on September 8th, 2011 at 8:31 am:

      Your comments ignore performance and suggest that code simplicity is paramount. When you have thousands of simultaneous transactions and terabytes of complex interrelated data, performance often determines what is possible.

      I didn’t say the speedup is because of compiled code, it is because of the number of discrete physical blocks that have to be accessed in a relational implementation vs a hierarchical one. The speedup I reported was not theoretical, it was actual. It was measured on real optimized databases on real optimized hardware with real user loads. The speedup was 50X to 100X (not 50% but 50 to 100 times faster). Orders of magnitude performance gains are significant in big systems, don’t you think?

      My measurements above included caching and were not disingenuous. The numbers are actual performance comparisons, not projected. They were measured on large memory supercomputers with huge caches. But there are limits to the problems caching can solve. Performance depends most on how many physical blocks have to be retrieved from disk to satisfy the query, and big databases don’t fit in cache, by definition. Relational implementations scatter the data you need across many blocks whereas a hierarchical implementation can deliver a complex bundle of data in a single physical read, depending on how it is organized and how it needs to be traversed.

      This is why indexedDB should be able to run circles around a traditional relational implementation when complex related data can be grouped hierarchically corresponding to traversal requirements. And this is why IndexedDB is a big step in the right direction. If you don’t like the language syntax then suggest an alternative, but avoid confusing syntax with the amount of work the hardware has to do under the hood.

      Reply

      1. Robert Brown wrote on September 15th, 2011 at 2:07 pm:

        Hi Bill,

        Your example would be 50 – 100 times faster because the data you are storing is highly hierarchical and therefore I’m guessing has only one relation defined, parent has children, that traverses the entire tree. If your system had more relations in it, I.E. parent has children and works for employer, you would see a very different result unless you store data multiple times in your XML db and that seems like you are asking for integrity issues and or circular reference problems.

        How do you resolve circular references in your XML? I’m curious because you say that the entire family is stored as a single data block. I.E. if the unthinkable happened, (and unfortunately it does) and someone has a child with one of their descendants, how can you store the entirety of the family when you hit that descendant, the entire tree above them can’t be repeated infinitely right?

        Specialized data can be sped up with a specialized storage mechanism, we are talking about (with a web standard) a generalized storage mechanism that should well for the widest variety of data with the lowest cost to maintenance (ease of use, difficulty in doing the “wrong” thing) while providing the highest performance possible. SQL and relational dbs have so far been the best compromise. There’s a reason that Google came up with BigTable for their proprietary DB, the data worked best with that structure, and performance outweighed the other items. Building a mechanical parts ordering system with BigTable is probably not a good use.

        IndexedDB doesn’t seem to be a good general data storage mechanism. It sounds like it’s a little too low level for use. I.E. data integrity is the user’s responsibility entirely, the ability to store completely different data types in one store with ease frankly scares me based on the developers that I’ve seen out there in the last 30 yrs. Why do people think it’s a good thing to be able to store People and Companies in the same logical data store?

        Reply

  20. devlim wrote on July 20th, 2011 at 10:18 am:

    Does the database still remain, after user clear the cache/cookies?

    Reply

    1. Michael wrote on September 1st, 2011 at 6:43 am:

      Yes, it does.
      The IndexedDB data is stored in a different location (in Chrome and FF there’s a dedicated folder for each domain), so a cache-cookies cleanup won’t affect the stored date.

      Reply

      1. Robert Brown wrote on September 15th, 2011 at 2:08 pm:

        You can however, clear the DB as well and if you aren’t savvy enough you can do it by accident when clearing cookies.

        Reply

  21. Ken Corey wrote on September 6th, 2011 at 1:23 pm:

    What a bunch of pretentious nonsense. The IndexedDB code is more complex, roughly the same size or bigger, and is rather like the argument about which end of an egg to open.

    Example 4 (websql) is readable by anyone who knows SQL. It’s obvious.
    Example 4 (IndexedDB) is a train wreck of Javascript.

    What are they thinking? Is it *really* this necessary to protect someone’s job?

    Reply

  22. Leigh Harrison wrote on September 20th, 2011 at 1:49 am:

    I have an existing desktop application I want to redevelop as a web app with off-line storage. It currently uses SQLite, has fourteen tables and builds its own dynamic queries based on user choices. Many of these queries contain multiple sub-queries and deeply nested WHERE clauses.

    I can port this to the Web SQL DB without substantial difficulty. Even contemplating the task with Indexed DB at a theoretical level is impossible.

    For some cases, Indexed DB may be a perfectly acceptable solution. But it’s not an appropriate tool for some of the work I hope to do. And I’m convinced that the web is the future of applications.

    Wny can’t we have both?

    Reply

    1. Paul wrote on September 21st, 2011 at 12:45 pm:

      If you read the comments by supporters I think that the reason is obvious. It’s politics.

      Supporters of KVP databases like Couch and Indexed DB (both mozilla pet projects) insist that we need a database that’s equally as scalable when it comes to read access when working with terabytes worth of information — inside a browser environment.

      They are also convinced that this performance increase is worth shirking the responsibilities that relational/SQL databases have taken head-on such as data integrity and native support for aggregate functions. These solutions shift the responsibility for those things to the application developer to handle through disciplined use of good design patterns. In exchange they get to claim better I/O times for the database without ever having to show any actual metrics on the impact to practical overall application performance.

      Supporters also insist that there is an additional advantage in keeping the SQL language from infecting web development…because when you’re working with the web, you should never have to work with multiple syntax structures and languages simultaneously.

      These supporters may be right, however I’ve seen no recommendations for any frameworks, reporting tools, or other development tools available for these databases…because they don’t exist. It would be an understatement to say that Indexed DB is in its infancy. Compare this to WebDB which is based on SQLite, with a host of development, reporting and testing tools and for anyone who actually wants to do practical application development the advantage is obvious…there is no justified reason for Mozilla not to support WebDB (at least until Indexed DB is mature) except for politics…multiple standards can and should be supported with offline storage just as multiple standards for document layouts (XML, HTML, XHTML, etc) are supported.

      Reply

      1. Daniel wrote on September 21st, 2011 at 1:10 pm:

        I wasn’t going to comment, but you mentioned there was no tooling and frameworks dealing with IndexedDB…and it just so happens I wrote one for an advanced MooTools repo that is, IMHO, absolutely phenomenal: https://github.com/csuwldcat/mootools-htmlx/blob/master/Source/IndexedDB/Database.js

        With this MooTools-based Database.js script, you don’t need to worry about async if you don’t want to (it has built-in queuing of async DB requests), you don’t have to keep regenerating connections to the DB (does if for you), and you get a ton of chainable helper methods that allow you to rock socks. Oh and did I mention you can bootstrap a schema with a JSON object if you like?

        How bout’ them apples ;)

        Reply

        1. Marcelo Cantos wrote on October 22nd, 2011 at 8:11 am:

          What about an equivalent to the sqlite3 CLI? I located and opened the add-ons database for my Firefox with sqlite3, issued a “.schema”, followed by a “SELECT name FROM addon;” and, lo and behold, I saw a list of Firefox add-ons I currently have installed. Now, this isn’t WebSQL, so I did a further test…

          I loaded http://project.mahemoff.com/sql.html in Chrome and added a couple of cities. I then loaded the corresponding database with sqlite3, confirmed that cities were stored with .schema then SELECT, added another city with INSERT and reloaded the web page. And there it was. The whole exercise took less than a minute, most of which was spent figuring out where Chrome stores its WebSQL databases.

          Consider how this degree of flexibility can impact the development process, especially if you choose from the plethora of extant GUI clients instead of the crufty old sqlite3 CLI, or even build your own tools using one of the many languages with SQLite bindings. For instance, the following Python script strains a list of city populations out of another web page and adds them to the WebSQL demo at http://project.mahemoff.com/sql.html. After a reload, the demo displays the populations of 100 cities.

          $ python -c ‘
          import sqlite3, urllib2, re
          conn = sqlite3.connect(“http_project.mahemoff.com_0/11″)
          conn.executemany(
          “INSERT INTO cities (name, population) VALUES (?, ?)”,
          sorted((city, int(pop.replace(“,”,”")))
          for line in urllib2.urlopen(“http://www.worldatlas.com/citypops.htm”)
          for m in [re.match(r"^\s*\d+\.\s+(.+?),.*?([\d,]+)”, unicode(line, “utf-8″))]
          if m
          for (city, pop) in [m.groups()]))
          conn.commit()

          I am sure plenty of effort is going into IndexedDB to make it easier to work with. But when Paul indicated that there was no tooling, I don’t think that 235 lines of API wrapper — lovely as those lines may be — are what he had in mind.

          Reply

          1. Daniel wrote on October 24th, 2011 at 9:15 am:

            I’m not sure you really understand the “API wrapper” you are seemingly dismissive of. First off, it isn’t just a wrapper. It offers convenient methods that people are use to working with when using JS natives like Array that don’t exist on the native IndexedDB object. Additionally it *eliminates entirely* the async handling for you and makes it so you *never* have to worry about whether your transaction objects are stale.

            You tipped your hand when you called it a *wrapper* and offhandedly dismissed it. At that point I knew you didn’t really give it a decent look, much less try it out ;)

          2. Marcelo Cantos wrote on October 24th, 2011 at 2:46 pm:

            @Daniel: Firstly, I did have a good look at it before commenting, and no, I wasn’t trying to be dismissive by calling it a wrapper. Even the raw SQLite API is much more difficult to code against than the C++/Python/Javascript/etc. wrappers, which also do more than just “wrap” the SQLite API. If I came across as dismissive, you have my unreserved apology; that wasn’t my intent.

            My point was, and still is, that a library that makes it easier to access the raw API — even one that improves async handling and adds support for storing additional data types — is a far cry from the wide range of tools, libraries and services that are available for SQLite. Do you dispute the claim that IndexedDB is in its infancy? That’s basically the claim Paul and I were making.

  23. Mike wrote on October 22nd, 2011 at 12:23 pm:

    this is why firefox is heading downhill, speed and functionality is lacking behind webkit:

    http://en.wikipedia.org/wiki/File:Usage_share_of_web_browsers_(Source_StatCounter).svg

    We choose to take the stance that if the user wants offline functionality in their app then they will have to use a webkit browser or IE w/ chrome frame. The server DB and iOS/Android apps are already using sql, writing the html5 app using a very simular database schema had many advantages. Sql works on almost all mobile devices and 80% of desktop browsers (using google frame)

    My users have no problem using a more advanced web browser to get offline functionality, most of them move to Chrome and never look back.

    Reply

  24. Shiby wrote on October 25th, 2011 at 4:51 am:

    I had made a post earlier : An exception coming in my Firefox when I run my sample code. But running the Trail Tool (http://nparashuram.com/trialtool/index.html#example=/ttd/IndexedDB/ie.html&selected=#prereq&amp;) it works fine in the same firefox window. Can anyone suggest what might me the issue?

    Reply

  25. Pingback from HTML5 WebDB vs IndexedDB » Jordan Wallwork on January 29th, 2012 at 7:13 am:

    [...] that the syntax was just awful compared to it’s SQL alternative. The code samples found at Mozilla Hacks show this pretty well (although it seems that the point of the post is supposed to sing the [...]

    Reply

1 2

Add your comment

  1.