esp32_arduino_sqlite3_lib icon indicating copy to clipboard operation
esp32_arduino_sqlite3_lib copied to clipboard

Slow work of insert data

Open Rita858 opened this issue 5 years ago • 7 comments

Hi @siara-cc , I found it is so slow for ESP3 to insert data. More detail: Test:

  • ESP32 inserted 100 records with four-column.
  • ESP32 search a specific record from 10000 records.

Result:

  • Esp32 took about 0.486s to retrieve while the insert took about 8s.

Question:

  • Why is ESP32 insert so slow?
  • How can I solve it?

I'm new to SQLite. Hope you reply when you are available. Thank you.

Rita858 avatar Sep 08 '20 09:09 Rita858

I think you have index in your database and whenever insertion happens in table index also has to be updated. Thats probably why it is slow. To solve the problem you could try tables using WITHOUT ROWID keyword and use the columns that need to be indexed as primary keys.

siara-cc avatar Sep 11 '20 19:09 siara-cc

I think you have index in your database and whenever insertion happens in table index also has to be updated. Thats probably why it is slow. To solve the problem you could try tables using WITHOUT ROWID keyword and use the columns that need to be indexed as primary keys.

But the thing is I have never used index in my table.

Rita858 avatar Sep 16 '20 07:09 Rita858

I have the same issue. Even when i try WITHOUT ROWID, its not faster. Sometimes the INSERT Transaction takes around 27seconds for just 1000 integer.

GithubPatrick91 avatar Sep 19 '20 11:09 GithubPatrick91

@Rita-GE @GithubPatrick91 I will try on my side. Meanwhile, if you are trying to store sensor data, this library: https://github.com/siara-cc/sqlite_micro_logger_arduino is more suitable. It can both read and write SQLite dbs, but it does not support SELECT, INSERT etc. You will have to use the given API. Please see the examples.

siara-cc avatar Sep 19 '20 12:09 siara-cc

I already tried this library - and like your lightweigth and fast µlogger lib.

But unfortunately the speed of the "finalize()" command decrease also continuously. When the database has around 1 million rows (3 columns) the finalize takes around ~13seconds ("partial_finalize()" is very fast and stable).

(info: i used the SELECT command of your sqlite3 library to display the table)

GithubPatrick91 avatar Sep 20 '20 07:09 GithubPatrick91

Have you tried using Prepared Statement to insert the records?

siara-cc avatar Dec 19 '20 14:12 siara-cc

Hi @siara-cc It was very useful to use your code

But i need your help I was inserting and updating large amount of data using sd card in sqlie3 db I was facing some errors in the SELECT query and will post the code below.

Code `#include <SD.h>

#include <stdio.h>

#include <stdlib.h>

#include <sqlite3.h>

#include <FS.h>

#include <WiFi.h>

#include <HTTPClient.h>

#include <ArduinoJson.h>

const char * host = "API KEY";

const char * wifiName = ""; const char * wifiPass = ""; bool Flag = false; int rc; sqlite3 * db;

const char * data = "Callback function called"; static int callback(void * data, int argc, char ** argv, char ** azColName) { int i; Serial.printf("%s: ", (const char * ) data); for (i = 0; i < argc; i++) { Serial.printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL"); } Serial.printf("\n"); return 1; } void listDir(fs::FS & fs, const char * dirname, uint8_t levels) { Serial.printf("Listing directory: %s\n", dirname);

File root = fs.open(dirname); if (!root) { Serial.println("Failed to open directory"); return; } if (!root.isDirectory()) { Serial.println("Not a directory"); return; }

File file = root.openNextFile(); while (file) { if (file.isDirectory()) { Serial.print(" DIR : "); Serial.println(file.name()); if (levels) { listDir(fs, file.name(), levels - 1); } } else { Serial.print(" FILE: "); Serial.print(file.name()); Serial.print(" SIZE: "); Serial.println(file.size()); } file = root.openNextFile(); } }

void testFileIO(fs::FS & fs, const char * path) { File file = fs.open(path); static uint8_t buf[512]; size_t len = 0; uint32_t start = millis(); uint32_t end = start; if (file) { len = file.size(); size_t flen = len; start = millis(); while (len) { size_t toRead = len; if (toRead > 512) { toRead = 512; } file.read(buf, toRead); len -= toRead; } end = millis() - start; Serial.printf("%u bytes read for %u ms\n", flen, end); file.close(); } else { Serial.println("Failed to open file for reading"); }

file = fs.open(path, FILE_WRITE); if (!file) { Serial.println("Failed to open file for writing"); return; }

size_t i; start = millis(); for (i = 0; i < 2048; i++) { file.write(buf, 512); } end = millis() - start; Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end); file.close(); }

int openDb(const char * filename, sqlite3 ** db) { int rc = sqlite3_open(filename, db); if (rc) { Serial.printf("open database: %s\n", sqlite3_errmsg( * db)); return rc; } else { Serial.printf("Opened database successfully\n"); } return rc; }

char * zErrMsg = 0; int db_exec(sqlite3 * db, const char * sql) { Serial.println(sql); long start = micros(); int rc = sqlite3_exec(db, sql, callback, (void * ) data, & zErrMsg); if (rc != SQLITE_OK) { Serial.printf("SQL error: %s\n", zErrMsg); sqlite3_free(zErrMsg); } else { Serial.printf("Operation done successfully\n"); } return rc; }

void setup() { Serial.begin(115200); delay(10); Serial.println();

Serial.print("Connecting to "); Serial.println(wifiName);

WiFi.begin(wifiName, wifiPass);

while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }

Serial.println(""); Serial.println("WiFi connected");

if (!SD.begin()) { Serial.println("Card Mount Failed"); return; } uint8_t cardType = SD.cardType();

if (cardType == CARD_NONE) { Serial.println("No SD card attached"); return; }

Serial.print("SD Card Type: "); if (cardType == CARD_MMC) { Serial.println("MMC"); } else if (cardType == CARD_SD) { Serial.println("SDSC"); } else if (cardType == CARD_SDHC) { Serial.println("SDHC"); } else { Serial.println("UNKNOWN"); }

uint64_t cardSize = SD.cardSize() / (1024 * 1024); Serial.printf("SD Card Size: %lluMB\n", cardSize);

listDir(SD, "/", 0);

char * zErrMsg = 0;

sqlite3_initialize();

}

void loop() { HTTPClient http;

http.begin(host);

int httpCode = http.GET(); String payload = http.getString();

Serial.println(httpCode); //200
Serial.println(payload);

if (openDb("/sd/NFC.db", & db)) return;

rc = db_exec(db, "CREATE TABLE IF NOT EXISTS NFCCardDetails (Physicalid String PRIMARY KEY ,WalletAmount Float)"); if (rc != SQLITE_OK) { sqlite3_close(db); return; }

if (httpCode == 200) { const size_t capacity = JSON_ARRAY_SIZE(23) + 23*JSON_OBJECT_SIZE(9) + 4930; DynamicJsonBuffer jsonBuffer(capacity);

JsonArray& root = jsonBuffer.parseArray(payload);
int sizeofArray = root.size();

for (int i = 0; i < sizeofArray; i++) {
  JsonObject & root_0 = root[i];
  const char* root_0_Physicalid = root_0["Physicalid"]; 
  int root_0_Walletamount = root_0["Walletamount"];

  String diff, sqlOpen, sqlClose, moduleOne, versionOne, Final, Where, sqlSelect;
  int Checker;
  String quote = ("'");
  moduleOne = String(root_0_Physicalid);
  versionOne = String(root_0_Walletamount);
  sqlSelect = String("SELECT * FROM NFCCardDetails where Physicalid=");
  Final = sqlSelect + quote + moduleOne + quote;
  int str_len = Final.length() + 1;
  char char_array[str_len];
  Final.toCharArray(char_array, str_len);
  
  Checker = db_exec(db, char_array);
  Serial.println(Checker);
   
  if(Checker == 0)
  {
    Serial.println("Inserting Value");
  sqlOpen = String("INSERT INTO NFCCardDetails VALUES (");
  diff = String(",");
  sqlClose = String(")");
  Final = sqlOpen + quote + moduleOne + quote + diff + quote + versionOne + quote + sqlClose;

  int str_len = Final.length() + 1;
  char char_array[str_len];
  Final.toCharArray(char_array, str_len);

  rc = db_exec(db, char_array);
  if (rc != SQLITE_OK) {
    sqlite3_close(db);
    return;
  }
  }else{
    Serial.println("Updating Value");
    sqlOpen = ("UPDATE NFCCardDetails SET WalletAmount = ");
    String quote = ("'");
    versionOne = String(root_0_Walletamount);
    Where = (" WHERE Physicalid = ");
    moduleOne = String(root_0_Physicalid);
    Final = sqlOpen + quote + versionOne + quote + Where + quote + moduleOne + quote;

    int str_len = Final.length() + 1;
    char char_array[str_len];
    Final.toCharArray(char_array, str_len);

    rc = db_exec(db, char_array);
    if (rc != SQLITE_OK) {
    sqlite3_close(db);
    return;
    }                
}    

} sqlite3_close(db); } }`

Error in serial monitor **Values are inserting and updating correctly, but im not ok with error Called

SQL error: query aborted

**

WiFi connected SD Card Type: SDHC SD Card Size: 15000MB Listing directory: / DIR : /System Volume Information FILE: /NFC.DB SIZE: 12288 **HERE i will print API data ** Opened database successfully CREATE TABLE IF NOT EXISTS NFCCardDetails (Physicalid String PRIMARY KEY ,WalletAmount Float) Operation done successfully SELECT * FROM NFCCardDetails where Physicalid='62:8a:2f:2e' Callback function called: Physicalid = 62:8a:2f:2e WalletAmount = 205.0

SQL error: query aborted 4 Updating Value UPDATE NFCCardDetails SET WalletAmount = '205' WHERE Physicalid = '62:8a:2f:2e' Operation done successfully SELECT * FROM NFCCardDetails where Physicalid='62:8a:2f:2e' Callback function called: Physicalid = 62:8a:2f:2e WalletAmount = 205.0

SQL error: query aborted 4 Updating Value UPDATE NFCCardDetails SET WalletAmount = '205' WHERE Physicalid = '62:8a:2f:2e' Operation done successfully SELECT * FROM NFCCardDetails where Physicalid='04:6b:43:3a:ec:64:80' Callback function called: Physicalid = 04:6b:43:3a:ec:64:80 WalletAmount = 88.0

Please help, Thanks in advance.

ram-prasanth-9394 avatar Jan 07 '21 07:01 ram-prasanth-9394