HTML5 IndexedDB, Web SQL Database and browser wars

半世苍凉 提交于 2019-11-28 03:27:45

Considering only WebSQL supports all three requirements you have listed, shouldn't your choice be simple? You have no insight into the development roadmap for Safari or Android, so use what you have available.

Well, as with all things computing, the game is "abstraction".

If you can come up with an adequate layer that works on both a SQL store and a key/value store, then, ideally you're isolated from the problem and can support the appropriate implementation on the particular browser. If your data model and access patterns don't fit with the lowest common denominator (i.e. a k/v store), then that pretty much solves your problem right there.

If you can use either store, then work on a decent access layer and approach the problem from that direction.

Mind, just because you have a k/v store on the back end doesn't mean you have to model your data as only a k/v model. Essentially all a DB is on the backend is a k/v store. If you don't have an insane amount of data, you can do many things. With a large amount of data the hoops you might have to jump through may cost you in performance that you may well not see with a smaller amount of data. All depends.

Are your database needs significantly beyond key/value stores? If not, I've found a number of javascript packages for local browser-based database abstraction. One such package is jStore:

http://code.google.com/p/jquery-jstore/

I recently used it to add local key/value storage. It's well-documented and the integration time was negligible -- it supports an array of storage backends, including flash local storage, through its API.

CouchDB is an excellent solution -- for a problem that is not quite congruent with yours. Check out couchone mobile. Not for strictly 'web apps' but it may provide a database foundation you could run with, if you have some flexibility with the specification.

My recommendation is to go for IndexDB, because there is an IndexDB Polyfill available.

All browsers supporting WebSQL can support the IndexDB API this way. The other way round would be very difficult to implement, so if you want to reach all browsers which know about some DB API, IndexDB is the best choice today.


Note: Even that this question is old it still is relevant, so I think the answers to this question deserve an update. And sorry for the link-only solution, so I added only links to usually long lasting destinations: W3C and GitHub

With your given requirement of Safari on iOS, there is no alternative but WebSQL. WebSQL is supported in other mobile browser like Opera and Blackberry. I don't think they will remove WebSQL support even if they have IndexedDB. Somehow they are complementary.

On the other hand, on browser storage war, IndexedDB win for good. IE and FF will only have IndexedDB. Ironic fact is that FF implements IndexedDB on top of Sqlite.

What I would like to say is IndexedDB is more than just key value store. It has index and transaction. These only two make almost all feature of SQL query including join, conditional and sorting. It is not obvious at first because of its asynchronous API.

Performance of IndexedDB is better than WebSQL. It is more secure. It is more flexible for javascript use case. Lastly it is more easier to use.

To illustrate the case, I will use sudo code from my library, but you can use IndexedDB API directly:

The 'people' store has index field 'name' and list indexed field 'hobby'. In JSON,

people = {
  name: 'Foo Bar',
  email: 'foo@bar.com'
  hobby: ['camping', 'swimming']};

To retrieve name from 'people' whose hobby is 'camping'.

var req = db.keys('people', 'hobby', IDBKeyRange.only('camping'));
req.done(function(campers) {
  db.keys('people', campers, 'name').done(function(names) {
     console.log(names);
  });
});

Interesting thing about this code is there is no serialisation involved. Hence it is very fast.

The following example illustrate friendship graph query. friendship object store has only one listed indexed field friend_list. It uses people object store key as out-of-line primary key. people object store has many attributes, among them is location field. The query is to find list of friends who know me and other_guy and located in 'Singapore'.

var q1 = new ydn.db.Iterator('friendship', 'friend_list', IDBKeyRange.only(me));
var q2 = new dn.db.Iterator('friendship', 'friend_list', IDBKeyRange.only(other_guy));
// if location is not indexed, a filtered value query is used.
var q3 = new ydn.db.Iterator('people', new ydn.db.Expression(['"location"', "'Singapore'", '=']));
// if location is indexed, an index query is used.
// var q3 = new ydn.db.Iterator('people', 'location', IDBKeyRange.only('Singapore'));
var current_loop = 2; // start from inner loop
var join_algo = function(keys, index_keys) {
  var advancement = [];
  advancement[keys.length - 1] = null;
  var has_adv = false;
  for (var i = 0; i < keys.length; i++) {
    if (!goog.isDef(keys[i])) {
      // completed iterator
      if (i != 0) {
        advancement[i] = false; // request to restart the iteration
        advancement[i - 1] = true; // advance outer iterator
        current_loop = i - 1;
      } // i == 0 means we are done.
     has_adv = true;
     break;
    }
  }
  if (!has_adv) {
    // continue looping current
    advancement[current_loop] = true;
  }
  return advancement;
}
var result = db.scan([q3, q1, q2], join_algo);
result.done(function(keys, index_keys, values) {
  console.log(values); // should get desire list of friends 
});

Again this join query is just key scanning and hence very fast. By default scan use sorted-merge algorithm to find matching keys, but here show naive nested-loop join algorithm. So table joining is possible, but you have to code join algorithm. But newer algorithms like zigzag merge are faster than possible with Sqlite because all inputs are sorted, cursors can advance at well and more importantly join process can exploit external knowledge that is not in the database. With SQL, join operation is opaque.

Other than that IndexedDB can be used techniques like streaming and map/reduce processing.

I'm replying to this in 2016 (5 years after you asked this question) and everything concerning the deprecation of WebSQL still stands. IndexedDB on the other hand, enjoys the support of all of the major browser vendors.

So to anyone who may find themselves here faced with the same decision to make, go with IndexedDB.

As implied by others here, however, such a decision isn't one that necessarily has to be made; one can simply choose (or make) a library which utilizes whichever database is available on a client machine.

BakedGoods differs from such libraries already suggested here in several ways; most pertinently, it allows the storage type(s) that are to be utilized to be explicitly specified, in turn allowing the developer to introduce other factors (such as performance characteristics) in to the decision-making process.

With it, conducting storage operations in whichever of the database types is supported is a matter of...

... specifying the appropriate operation options and equivalent configs for both database types:

//If the operation is a set(), and the referenced structures 
//don't exist, they will be created automatically.

var webSQLOptionsObj = {
    databaseName: "Example_DB",
    databaseDisplayName: "Example DB",
    databaseVersion: "",
    estimatedDatabaseSize: 1024 * 1024,
    tableData: {
        name: "Main",
        keyColumnName: "lastName",
        columnDefinitions: "(lastName TEXT PRIMARY KEY, firstName TEXT)"
    }, 
    tableIndexDataArray: [name: "First_Name_Index", columnNames: "(firstName)"]
};

var indexedDBOptionsObj = {
    databaseName: "Example_DB",
    databaseVersion: 1,
    objectStoreData: {
        name: "Main",
        keyPath: lastName,
        autoIncrement: false
    },
    objectStoreIndexDataArray: [
        {name: "First_Name_Index", keyPath: "firstName", unique: false, multiEntry: false}
    ],
};

var optionsObj = {
    conductDisjointly: false, 
    webSQL: webSQLOptionsObj, 
    indexedDB: indexedDBOptionsObj
};

... and conducting the operation:

bakedGoods.set({
    data: [
        {value: {lastName: "Obama", firstName: "Barack"}}, 
        {value: {lastName: "Biden", firstName: "Joe"}}
    ],
    storageTypes: ["indexedDB", "webSQL"],
    options: optionsObj,
    complete: function(byStorageTypeStoredItemRangeDataObj, byStorageTypeErrorObj){}
});

Its simple interface and unmatched storage facility support comes at the cost of lack of support for some storage facility-specific configurations. For instance, it does not support the conduction of storage operations in WebSQL tables with multi-column primary keys.

So if you make heavy use of those types of features, you may want to look elsewhere.

Oh, and for the sake of complete transparency, BakedGoods is maintained by yours truly :) .

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!