HTML5 IndexedDB、Web SQL 数据库和浏览器之战

发布于 2024-09-28 08:20:56 字数 902 浏览 8 评论 0原文

我正在开始开发一个具有离线数据库存储需求的网络应用程序。长话短说,该应用程序应该能够运行在:

  • 主要桌面浏览器之一,Chrome 首选
  • iOS 上的 Safari
  • Android 的本机浏览器(基于 V8 和 WebKit)

所以问题是选择哪种技术:IndexedDB 还是 Web SQL Database?

对于Web SQL数据库,一方面,它已经准备好用于上述任何场景。另一方面,Mozilla 表示 Firefox 永远不会实现它,并且根据 HTML5 工作草案该规范已陷入僵局:

该规范已陷入僵局:所有感兴趣的实现者都使用相同的 SQL 后端(Sqlite),但我们需要多个独立的实现来沿着标准化路径前进。在另一个实现者有兴趣实现此规范之前,SQL 方言的描述一直保留为对 Sqlite 的简单引用,这对于标准来说是不可接受的。如果您是一个有兴趣实现独立 SQL 后端的实现者,请联系编辑,以便他可以为该方言编写规范,从而使该规范能够向前发展。

IndexedDB 是 Mozilla 提倡的替代方案,但它只会出现在 Firefox 4 中。微软对此很感兴趣,Chrome 也会支持它。我对 Apple 关于 IndexedDB 的计划一无所知。

我个人倾向于选择Web SQL数据库,但只是因为我习惯了SQLite,我喜欢SQL的强大功能和表现力,并且我了解关系模型。 IndexedDB 对我来说是一种不确定性。

也就是说,我担心赌错了马。即使 IndexedDB 成为标准,是否可以假设对 Web SQL 数据库的支持将继续存在?

(关于 CouchDB 的注释:您是否也将其视为替代方案?)

I'm starting the development of a web app with offline database storage requirements. Long story short, the app should be able to run on:

  • One of the major desktop browsers, Chrome preferred
  • Safari on iOS
  • Android's native browser (based on V8 and WebKit)

So the question is which technology to choose: IndexedDB or Web SQL Database?

Regarding Web SQL Database, on one hand, it is ready to be used in any of the above scenarios. On the other, Mozilla has stated Firefox will never implement it, and acording to the HTML5 working draft the specification has reached an impasse:

This specification has reached an impasse: all interested implementors have used the same SQL backend (Sqlite), but we need multiple independent implementations to proceed along a standardisation path. Until another implementor is interested in implementing this spec, the description of the SQL dialect has been left as simply a reference to Sqlite, which isn't acceptable for a standard. Should you be an implementor interested in implementing an independent SQL backend, please contact the editor so that he can write a specification for the dialect, thus allowing this specification to move forward.

IndexedDB is the alternative advocated by Mozilla, but it will only come in Firefox 4. Microsoft is interested and Chrome will support it as well. I know nothing of Apple's plans regarding IndexedDB.

I'm personally inclined to choose Web SQL Database, but just because I'm used to SQLite, I like the power and expressiveness of SQL, and I understand the relational model. IndexedDB, for me, is an uncertainty.

That said, I'm afraid of betting on the wrong horse. Is it safe to assume support for Web SQL Database will continue to exist, even if IndexedDB becomes the standard?

(A note on CouchDB: do you also see it as an alternative?)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

吝吻 2024-10-05 08:20:56

嗯,就像所有的计算一样,游戏是“抽象的”。

如果您能够提供一个既适用于 SQL 存储又适用于键/值存储的适当层,那么理想情况下您就可以摆脱问题,并且可以支持特定浏览器上的适当实现。如果您的数据模型和访问模式不符合最低公分母(即 ak/v 存储),那么这几乎可以解决您的问题。

如果您可以使用任一商店,那么就建立一个合适的访问层并从该方向解决问题。

请注意,后端有 ak/v 存储并不意味着您必须将数据建模为仅 ak/v 模型。本质上,后端的所有数据库都是 ak/v 存储。如果您没有大量的数据,您可以做很多事情。对于大量数据,您可能必须跳过的障碍可能会降低您的性能,而对于较小数据量,您可能不会看到这种情况。一切都取决于。

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.

悍妇囚夫 2024-10-05 08:20:56

考虑到只有 WebSQL 支持您列出的所有三个要求,您的选择难道不应该很简单吗?您对 Safari 或 Android 的开发路线图没有深入的了解,因此请使用您现有的资源。

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.

吻泪 2024-10-05 08:20:56

我在 2016 年回复此问题(在您提出这个问题 5 年后),有关 弃用 WebSQL 的所有内容仍然有效。另一方面,IndexedDB 享受所有主要浏览器供应商的支持

因此,对于任何可能面临同样决定的人来说,请选择 IndexedDB。

然而,正如其他人所暗示的那样,这样的决定并不是必须做出的;而是必须做出的。人们可以简单地选择(或创建)一个库,该库利用客户端计算机上可用的任何数据库。

BakedGoods 与此处已经建议的此类库在几个方面有所不同;最相关的是,它允许显式指定要使用的存储类型,从而允许开发人员在决策过程中引入其他因素(例如性能特征)。

有了它,在支持的数据库类型中执行存储操作只需......

为两种数据库类型指定适当的操作选项和等效配置:

//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
};

......并执行操作:

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

其简单的界面和无与伦比的功能存储设施支持的代价是缺乏对某些存储设施特定配置的支持。例如,不支持对多列主键的WebSQL表进行存储操作。

因此,如果您大量使用这些类型的功能,您可能需要寻找其他地方。

哦,为了完全透明,BakedGoods 确实由您维护:)。

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 :) .

╰沐子 2024-10-05 08:20:56

我的建议是选择 IndexDB,因为有一个IndexDB Polyfill >可用。

所有支持 WebSQL 的浏览器都可以通过这种方式支持 IndexDB API。反之则很难实现,因此如果您想覆盖所有了解某些 DB API 的浏览器,IndexDB 是当今的最佳选择。


注意:即使这个问题很旧,但它仍然相关,所以我认为这个问题的答案值得更新。对于仅链接解决方案感到抱歉,因此我仅添加了通常持久目的地的链接:W3C 和 GitHub

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

短暂陪伴 2024-10-05 08:20:56

您的数据库需求是否远远超出了键/值存储?如果没有,我已经找到了许多用于基于本地浏览器的数据库抽象的 javascript 包。 jStore 就是这样的一个软件包:

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

我最近用它来添加本地键/值存储。它有详细的文档记录,并且集成时间可以忽略不计——它通过其 API 支持一系列存储后端,包括闪存本地存储。

对于与您的问题不太一致的问题,CouchDB 是一个出色的解决方案。请查看 couchone 移动。不适用于严格的“网络应用程序”,但如果您对规范有一定的灵活性,它可能会提供您可以运行的数据库基础。

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.

马蹄踏│碎落叶 2024-10-05 08:20:56

根据您对 iOS 上 Safari 的特定要求,除了 WebSQL 之外别无选择。 Opera 和 Blackberry 等其他移动浏览器也支持 WebSQL。我认为即使他们有 IndexedDB,他们也不会删除 WebSQL 支持。某种程度上它们是互补的。

另一方面,在浏览器存储战争中,IndexedDB 永远获胜。 IE和FF只会有IndexedDB。一个讽刺的事实是,FF 在 Sqlite 之上实现了 IndexedDB。

我想说的是 IndexedDB 不仅仅是一个键值存储。它有索引和交易。仅这两个就提供了 SQL 查询的几乎所有功能,包括连接、条件和排序。由于其异步 API,一开始并不明显。

IndexedDB 的性能优于 WebSQL。它更安全。它对于 javascript 用例来说更加灵活。最后它更容易使用。

为了说明这种情况,我将使用我的库中的伪代码,但您可以使用 IndexedDB API直接:

“people”存储有索引字段“name”和列表索引字段“hobby”。在 JSON 中,

people = {
  name: 'Foo Bar',
  email: '[email protected]'
  hobby: ['camping', 'swimming']
};

从爱好是“露营”的“人”中检索姓名。

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

这段代码的有趣之处在于不涉及序列化。因此它非常快。

下面的例子说明了友谊图查询。 friendship 对象存储只有一个列出的索引字段friend_list。它使用人员对象存储键作为外联主键。 people 对象存储有很多属性,其中有 location 字段。该查询旨在查找认识 meother_guy 且位于“新加坡”的好友列表。

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 
});

同样,这个连接查询只是按键扫描,因此速度非常快。默认情况下,scan 使用排序合并算法来查找匹配键,但此处显示了一种简单的嵌套循环连接算法。因此表连接是可能的,但您必须编写连接算法。但是像 zigzag merge 这样的新算法比 Sqlite 更快,因为所有输入都已排序,游标也可以前进,更重要的是,连接过程可以利用数据库中没有的外部知识。对于 SQL,连接操作是不透明的。

除此之外,IndexedDB 还可以使用流处理和 Map/Reduce 处理等技术。

With your given requirement of Safari on iOS, there is no alternative but WebSQL. WebSQL is supported in other mobile browsers 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, in the browser storage war, IndexedDB has won for good. IE and FF will only have IndexedDB. An ironic fact is that FF implements IndexedDB on top of Sqlite.

What I would like to say is IndexedDB is more than just a key value store. It has indexes and transactions. These two alone provide almost all features 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 easier to use.

To illustrate the case, I will use pseudo 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: '[email protected]'
  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 a sorted-merge algorithm to find matching keys, but here shows a naive nested-loop join algorithm. So table joining is possible, but you have to code the join algorithm. But newer algorithms like zigzag merge are faster than possible with Sqlite because all inputs are sorted, cursors can advance as well and more importantly the join process can exploit external knowledge that is not in the database. With SQL, the join operation is opaque.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文