Re[2]: Ускорение работы с sqlite
От: rudzuk  
Дата: 16.07.23 09:40
Оценка:
Здравствуйте, Anton Batenev, Вы писали:

AB> Пример вставки 100К записей за ~15 секунд (обработка ошибок заменена на паники для упрощения).


Чего так медленно?

Попробовал на FPC:
program project1;
uses
  SysUtils, SQLite3Wrap;
var
  db : TSQLite3Database;
  st : TSQLite3Statement;
  i  : Integer;
begin
  db := TSQLite3Database.Create;
  try
    db.Open('data.db');
    db.Execute('CREATE TABLE IF NOT EXISTS test (' +
               'key    INTEGER NOT NULL PRIMARY KEY,' +
               'value  TEXT    NOT NULL)');

    st := db.Prepare('INSERT OR REPLACE INTO "test" ("key", "value") VALUES (?, ?)');

    db.BeginTransaction;
    try
      for i := 0 to 100000 - 1 do
      begin
        //db.Execute(Format('INSERT OR REPLACE INTO "test" ("key", "value") VALUES (%u, %u)', [i, i*2]));
        st.BindInt(1, i);
        st.BindInt(2, i * i);
        st.StepAndReset;
      end;

      db.Commit;
    except
      db.Rollback;
      raise;
    end;

  finally
    db.Free;
  end;
end.

Без стейтмента — около 1 сек. Со стейтментом — 350 мсек.
avalon/3.0.2
Re[3]: Ускорение работы с sqlite
От: rudzuk  
Дата: 16.07.23 09:51
Оценка:
Здравствуйте, rudzuk, Вы писали:

Поправил немного код (не сразу заметил, что второй параметр текстовый. время почти не изменилось):
program project1;
uses
  SysUtils, SQLite3Wrap;
var
  db : TSQLite3Database;
  st : TSQLite3Statement;
  i  : Integer;
begin
  db := TSQLite3Database.Create;
  try
    db.Open('data.db');
    db.Execute('CREATE TABLE IF NOT EXISTS test (' +
               'key    INTEGER NOT NULL PRIMARY KEY,' +
               'value  TEXT    NOT NULL)');

    st := db.Prepare('INSERT OR REPLACE INTO "test" ("key", "value") VALUES (?, ?)');
    try
      db.BeginTransaction;
      try
        for i := 0 to 100000 - 1 do
        begin
          //db.Execute(Format('INSERT OR REPLACE INTO "test" ("key", "value") VALUES (%u, %s)', [i, (i*2).ToString]));
          st.BindInt(1, i);
          st.BindText(2, (i * i).ToString);
          st.StepAndReset;
        end;

        db.Commit;
      except
        db.Rollback;
        raise;
      end;
    finally
      st.Free;
    end;
  finally
    db.Free;
  end;
end.
avalon/3.0.2
Re: Ускорение работы с sqlite
От: vsb Казахстан  
Дата: 16.07.23 10:12
Оценка:
На каком оборудовании это работает? Полсекунды это очень много, даже для крутящегося жёсткого диска.

Я на Go работал с sqlite, правда без прослоек, таких задержек не было.

Я бы предложил сократить задачу до конкретного примера в несколько десятков строк без лишних библиотек и на него уже смотреть. А так рассуждать абстрактно можно много.
Отредактировано 16.07.2023 10:15 vsb . Предыдущая версия . Еще …
Отредактировано 16.07.2023 10:14 vsb . Предыдущая версия .
Отредактировано 16.07.2023 10:13 vsb . Предыдущая версия .
Re[4]: Ускорение работы с sqlite
От: vsb Казахстан  
Дата: 16.07.23 10:16
Оценка:
Здравствуйте, alex_public, Вы писали:

_>>>P.S. Да, и надеюсь ты не забыл там, что sqlite строго однопоточная?

M>>Разве? Я там мьютексы какие-то видел

_>Я не в том смысле, что нельзя обращаться из разных потоков, а в том что это будет только замедлять работу, т.к. каждый запрос блокирует всю базу. Это как раз отличие sqlite от "взрослых" СУБД, в которых одновременные запросы могут реально исполняться параллельно (если они конечно не на одну строчку указывают).


wal режим там уже сто лет как есть.
Re[3]: Ускорение работы с sqlite
От: Anton Batenev Россия https://github.com/abbat
Дата: 16.07.23 11:43
Оценка:
Здравствуйте, rudzuk, Вы писали:

r> AB> Пример вставки 100К записей за ~15 секунд (обработка ошибок заменена на паники для упрощения).

r> Чего так медленно?

Подозреваю, что из за сишных биндингов (go не очень хорошо работает с такими) и из за моего старого ноута. Но т.к. смысл примера был лишь продемонстрировать идею, то я даже не стал копаться.
Re[3]: Ускорение работы с sqlite
От: Anton Batenev Россия https://github.com/abbat
Дата: 16.07.23 11:43
Оценка: 4 (1)
Здравствуйте, DiPaolo, Вы писали:

DP> Что не так с gorm?


Тут наверное в КСВ сразу можно будет переносить Любой ORM рано или поздно превращается в боль, страдания, костыли и/или абсолютно неоптимальные планы. За исключением случая когда ORM возводится в абсолют и схему базы костылят под возможности и логику ORM, а не наоборот.

DP> Что можешь порекомендовать взамен?


"Нативная" (с минимальной прослойкой) работа с БД (в данном случае через интерфейс database/sql, но это совершенно не обязательно)
Re[4]: Ускорение работы с sqlite
От: rudzuk  
Дата: 16.07.23 12:00
Оценка:
Здравствуйте, Anton Batenev, Вы писали:

AB> r> Чего так медленно?


AB> Подозреваю, что из за сишных биндингов (go не очень хорошо работает с такими) и из за моего старого ноута. Но т.к. смысл примера был лишь продемонстрировать идею, то я даже не стал копаться.


У меня десктоп тоже древний, с HDD, на нем твой код вообще 48 сек. работает (диск постоянно трещит). Вряд ли это биндинги...
avalon/3.0.2
Re[4]: Ускорение работы с sqlite
От: rudzuk  
Дата: 16.07.23 12:06
Оценка:
Здравствуйте, Anton Batenev, Вы писали:

AB> Подозреваю, что из за сишных биндингов (go не очень хорошо работает с такими) и из за моего старого ноута. Но т.к. смысл примера был лишь продемонстрировать идею, то я даже не стал копаться.


Стало интересно. Посмотрел в otop, твой пример пишет на диск около 3 GB Определенно не в биндингах дело...
avalon/3.0.2
Re[5]: Ускорение работы с sqlite
От: rudzuk  
Дата: 16.07.23 12:08
Оценка:
Здравствуйте, rudzuk, Вы писали:

r> Стало интересно. Посмотрел в otop, твой пример пишет на диск около 3 GB Определенно не в биндингах дело...


Мой код записывает около 3.5 Mb. Размеры баз одинаковые (после того, как я в свой код твои прагмы вставил) 1,933,312 bytes.
avalon/3.0.2
Re: Ускорение работы с sqlite
От: CRT  
Дата: 02.08.23 10:37
Оценка: 4 (1)
Выполни вначале команду sql(ite)
PRAGMA synchronous = OFF

и sqlite не будет дожидаться физической записи на диск при операциях вставки и обновления.

Работать будет ГОРАЗДО быстрее.
Опасность такая: если операционная система зависнет или питание выключат в неподходящий момент, то БД может повредиться.
При этом если только твое приложение вылетит, то с данными всё будет в порядке в любом случае.

https://www.sqlite.org/pragma.html#pragma_synchronous

OFF (0)
With synchronous OFF (0), SQLite continues without syncing as soon as it has handed data off to the operating system. If the application running SQLite crashes, the data will be safe, but the database might become corrupted if the operating system crashes or the computer loses power before that data has been written to the disk surface. On the other hand, commits can be orders of magnitude faster with synchronous OFF.

Re[2]: Ускорение работы с sqlite
От: Maniacal Россия  
Дата: 02.08.23 12:56
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Если несколько изменений объединены в одну транзакцию, то вся эта долгая возня с обеспечением синхронизации с диском делится на них на всех. Ускорение может быть на несколько порядков (грубо говоря, одно изменение и 10000 изменений, объединенных в одну транзакцию, занимают довольно сравнимое время).


Кстати, чуть-чуть оффтоп, но на ту же тему. Если в PostgreSQL заменить поштучное чтение 1 млн. записей из БД на bulk-чтение порциями сразу по 1 тыс. записей за раз, даже скорость чтения возрастает на пару порядков. Но тут капитан Очевидность уже давно майор или даже подполковник в этом вопросе. В Оракле, помнится, практически по барабану было. Там сервер с клиентом сразу фишечку просекали, что булками читаться будет и результат кешировался на стороне клиентской библиотеки, даже если курсор создавался для поштучного чтения. ЕМНИП. Читало небольшую булку, потом уже на стороне клиента поштучно расковыривало.
Re[5]: Ускорение работы с sqlite
От: Maniacal Россия  
Дата: 02.08.23 13:00
Оценка: 1 (1)
Здравствуйте, LaptevVV, Вы писали:

LVV>В Си есть include-вариант sqllite — там всего 3 h-файла


Я тупо скописастил все исходники в один хедер, пахало.
Re: Ускорение работы с sqlite
От: zx zpectrum  
Дата: 12.08.23 04:54
Оценка:
https://blog.expensify.com/2018/01/08/scaling-sqlite-to-4m-qps-on-a-single-server/
https://review.firstround.com/your-database-is-your-prison-heres-how-expensify-broke-free
https://github.com/Expensify/Bedrock

Барретт, конечно, весьма неоднозначный человек, в том плане, что любит восторженно абсолютизировать спорные подходы, которые применимы далеко не всегда, не везде и не для всех, однако sqlite он раскочегаривал так, что мое почтение. Хоть и не на go, но его наработки, возможно, будут полезны для ознакомления.
Re[2]: Ускорение работы с sqlite
От: johny5 Новая Зеландия
Дата: 27.11.23 01:35
Оценка:
Здравствуйте, CRT, Вы писали:

CRT>Выполни вначале команду sql(ite)

CRT>
CRT>PRAGMA synchronous = OFF
CRT>

CRT>и sqlite не будет дожидаться физической записи на диск при операциях вставки и обновления.

О, круто, спасибо. А я в сорцах вызов flush() удалял. Правда это было лет 10 назад...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.