In IndexedDB, what is the difference between IDBObjectStore.put and IDBCursor.update?

In IndexedDB, there are two ways to update an object already in the database. You can call IDBCursor.update or IDBObjectStore.put .

Both accept the updated object as a parameter.

IDBCursor.update is required to open the cursor first, but basically you have to do this with IDBObjectStore.put to get the previous value.

IDBObjectStore.put will create a new object if it cannot find it for the update, but since it must check the update first, I don’t know if this would really create a performance difference.

So what is the difference between these methods? Is there something I'm missing? I tried to make a test case to investigate performance differences:

 var db; function runTest(N, cb) { console.log("N = " + N); // Add some fake data to object store var tx = db.transaction("store", "readwrite"); tx.objectStore("store").clear(); for (var i = 0; i < N; i++) { tx.objectStore("store").add({"id": i, "index":0,"guid":"21310c91-ff31-4cb9-ae68-16d48cbbd84a","isActive":false,"balance":"$1,840.25","picture":"http://placehold.it/32x32","age":33,"eyeColor":"brown","name":"Witt Fletcher","gender":"male","company":"QUILM","email":" wittfletcher@quilm.com ","phone":"+1 (851) 485-2174","address":"729 Conover Street, Marenisco, Virginia, 7219","about":"Incididunt do deserunt ut quis. Exercitation et ut ad aliqua ut do sint Lorem. Aliquip sit aliquip nulla excepteur pariatur ut laborum ea dolor. Consectetur incididunt et et esse commodo id eu dolor in. Nostrud sit mollit occaecat ullamco commodo aute anim duis enim et aliqua. Aute duis nostrud do minim labore sunt mollit in voluptate aliquip sit. Aliqua aliquip non ipsum exercitation cillum irure in.\r\n","registered":"2014-07-02T03:42:57 +04:00","latitude":-65.942119,"longitude":-129.471674,"tags":["reprehenderit","nostrud","velit","exercitation","nulla","nulla","est"],"friends":[{"id":0,"name":"Kristine Francis"},{"id":1,"name":"Lizzie Ruiz"},{"id":2,"name":"Bobbie Underwood"}],"greeting":"Hello, Witt Fletcher! You have 7 unread messages.","favoriteFruit":"apple"}); } tx.oncomplete = function () { // Update with cursor.update var tStart = (new Date()).getTime(); tx = db.transaction("store", "readwrite"); var store = tx.objectStore("store"); for (var i = 0; i < N; i++) { store.openCursor(i).onsuccess = function (event) { var cursor = event.target.result; cursor.value.age = 34; cursor.update(cursor.value); }; } tx.oncomplete = function () { var tEnd = (new Date()).getTime(); console.log("cursor.update - " + (tEnd - tStart) + " milliseconds"); // Update with put tStart = (new Date()).getTime(); tx = db.transaction("store", "readwrite"); store = tx.objectStore("store"); for (var i = 0; i < N; i++) { store.openCursor(i).onsuccess = function (event) { var cursor = event.target.result; cursor.value.age = 34; store.put(cursor.value); }; } tx.oncomplete = function () { tEnd = (new Date()).getTime(); console.log("put - " + (tEnd - tStart) + " milliseconds"); if (cb !== undefined) { cb(); } }; }; }; } request = indexedDB.open("yes5ytrye", 1); request.onerror = function (event) { console.log(event); }; request.onupgradeneeded = function (event) { var db = event.target.result; db.onerror = function (event) { console.log(event); }; db.createObjectStore("store", {keyPath: "id"}); }; request.onsuccess = function (event) { db = request.result; db.onerror = function (event) { console.log(event); }; runTest(100, function () { runTest(1000, function () { runTest(10000, function () { console.log("Done"); }); }); }); }; 

You can try it here .

In Firefox, I get output like:

 N = 100 cursor.update - 39 milliseconds put - 40 milliseconds N = 1000 cursor.update - 229 milliseconds put - 256 milliseconds N = 10000 cursor.update - 2194 milliseconds put - 2096 milliseconds Done 

In principle, the difference in performance. The results are slightly different in Chrome when N is large:

 N = 100 cursor.update - 51 milliseconds put - 44 milliseconds N = 1000 cursor.update - 414 milliseconds put - 447 milliseconds N = 10000 cursor.update - 13506 milliseconds put - 22783 milliseconds Done 

But, as I said above, I'm not even sure if there should be a difference between the two methods, because it seems that they should do the same.

+5
source share
2 answers

The main difference between update cursor and put is that you need to get the element you want to update with cursor ; on the other hand, when using the put operator, you only need to know the id element you are updating, and you simply execute the put function, which is defined at the store level. However, this speed will only work if you have a complete object stored in memory.

I updated your code a bit and got the speed:

 var db; function runTest(N, cb) { console.log("N = " + N); // Add some fake data to object store var tx = db.transaction("store", "readwrite"); tx.objectStore("store").clear(); for (var i = 0; i < N; i++) { tx.objectStore("store").add({"id": i, "index":0,"guid":"21310c91-ff31-4cb9-ae68-16d48cbbd84a","isActive":false,"balance":"$1,840.25","picture":"http://placehold.it/32x32","age":33,"eyeColor":"brown","name":"Witt Fletcher","gender":"male","company":"QUILM","email":" wittfletcher@quilm.com ","phone":"+1 (851) 485-2174","address":"729 Conover Street, Marenisco, Virginia, 7219","about":"Incididunt do deserunt ut quis. Exercitation et ut ad aliqua ut do sint Lorem. Aliquip sit aliquip nulla excepteur pariatur ut laborum ea dolor. Consectetur incididunt et et esse commodo id eu dolor in. Nostrud sit mollit occaecat ullamco commodo aute anim duis enim et aliqua. Aute duis nostrud do minim labore sunt mollit in voluptate aliquip sit. Aliqua aliquip non ipsum exercitation cillum irure in.\r\n","registered":"2014-07-02T03:42:57 +04:00","latitude":-65.942119,"longitude":-129.471674,"tags":["reprehenderit","nostrud","velit","exercitation","nulla","nulla","est"],"friends":[{"id":0,"name":"Kristine Francis"},{"id":1,"name":"Lizzie Ruiz"},{"id":2,"name":"Bobbie Underwood"}],"greeting":"Hello, Witt Fletcher! You have 7 unread messages.","favoriteFruit":"apple"}); } tx.oncomplete = function () { // Update with cursor.update var tStart = (new Date()).getTime(); tx = db.transaction("store", "readwrite"); var store = tx.objectStore("store"); for (var i = 0; i < N; i++) { store.openCursor(i).onsuccess = function (event) { var cursor = event.target.result; cursor.value.age = 34; cursor.update(cursor.value); }; } tx.oncomplete = function () { var tEnd = (new Date()).getTime(); console.log("cursor.update - " + (tEnd - tStart) + " milliseconds"); // Update with put tStart = (new Date()).getTime(); tx = db.transaction("store", "readwrite"); store = tx.objectStore("store"); for (var i = 0; i < N; i++) { //you don't need the element just update store.put({"id": i, "index":0,"guid":"21310c91-ff31-4cb9-ae68-16d48cbbd84a","isActive":false,"balance":"$1,840.25","picture":"http://placehold.it/32x32","age":33,"eyeColor":"brown","name":"Witt Fletcher","gender":"male","company":"QUILM","email":" wittfletcher@quilm.com ","phone":"+1 (851) 485-2174","address":"729 Conover Street, Marenisco, Virginia, 7219","about":"Incididunt do deserunt ut quis. Exercitation et ut ad aliqua ut do sint Lorem. Aliquip sit aliquip nulla excepteur pariatur ut laborum ea dolor. Consectetur incididunt et et esse commodo id eu dolor in. Nostrud sit mollit occaecat ullamco commodo aute anim duis enim et aliqua. Aute duis nostrud do minim labore sunt mollit in voluptate aliquip sit. Aliqua aliquip non ipsum exercitation cillum irure in.\r\n","registered":"2014-07-02T03:42:57 +04:00","latitude":-65.942119,"longitude":-129.471674,"tags":["reprehenderit","nostrud","velit","exercitation","nulla","nulla","est"],"friends":[{"id":0,"name":"Kristine Francis"},{"id":1,"name":"Lizzie Ruiz"},{"id":2,"name":"Bobbie Underwood"}],"greeting":"Hello, Witt Fletcher! You have 7 unread messages.","favoriteFruit":"apple"}); } tx.oncomplete = function () { tEnd = (new Date()).getTime(); console.log("put - " + (tEnd - tStart) + " milliseconds"); if (cb !== undefined) { cb(); } }; }; }; } request = indexedDB.open("yes5ytrye", 1); request.onerror = function (event) { console.log(event); }; request.onupgradeneeded = function (event) { var db = event.target.result; db.onerror = function (event) { console.log(event); }; db.createObjectStore("store", {keyPath: "id"}); }; request.onsuccess = function (event) { db = request.result; db.onerror = function (event) { console.log(event); }; runTest(100, function () { runTest(1000, function () { runTest(10000, function () { console.log("Done"); }); }); }); }; 

Here are my results:

 N = 100 cursor.update - 46 milliseconds put - 28 milliseconds N = 1000 cursor.update - 157 milliseconds put - 114 milliseconds N = 10000 cursor.update - 5530 milliseconds put - 2391 milliseconds Done 
+3
source

Yes, they are the same in the sense that they both use to update record values. Use a simple put if you already know the key and value, otherwise any minimized cursor update will be just an option.

Performance must be the same for updating a record.

+2
source

Source: https://habr.com/ru/post/1209014/


All Articles