Comments 33
благодарю за 3-ую часть.
+1
Отдельное спасибо за присоединение базы данных в памяти, этого-то мне и не хватало. :)
0
Спасибо за всю статью! :)
-1
Пожалуйста, не кидайте в меня гнилыми помидорами, а, напишите, что же все-таки, конкретно нужно сделать, чтобы БЫСТРО вставить 100500 записей в таблицу (желательно с примером кода)?
+1
Если база пустая (не жалко потерять):
PRAGMA synchronous = 0;
PRAGMA journal_mode = OFF;
BEGIN;
INSERT INTO XXX ...;
INSERT INTO XXX ...;
… 10000 вставок…
COMMIT;
BEGIN;
INSERT INTO XXX ...;
INSERT INTO XXX ...;
… 10000 вставок…
COMMIT;
… пока все не вставится…
PRAGMA synchronous = FULL;
PRAGMA journal_mode = DELETE;
PRAGMA synchronous = 0;
PRAGMA journal_mode = OFF;
BEGIN;
INSERT INTO XXX ...;
INSERT INTO XXX ...;
… 10000 вставок…
COMMIT;
BEGIN;
INSERT INTO XXX ...;
INSERT INTO XXX ...;
… 10000 вставок…
COMMIT;
… пока все не вставится…
PRAGMA synchronous = FULL;
PRAGMA journal_mode = DELETE;
+3
Добавил в конец статьи ссылки про оптимизацию вставок в SQLite
+1
0. Прибить имеющиеся индексы
1. Заворачиваешь порции Insert-ов по несколько тысяч в транзакции
2. Разделяешь создание запросов и их исполнение по разным thread, ибо первое — CPU, а второе IO bound.
3. Ждешь окончания транзакций и перестраиваешь индексы.
Пример кода ( под iPhone + немного страшен из-за некоторых попыток оптимизации )
github.com/dodikk/CsvToSqlite
Дерзай.
1. Заворачиваешь порции Insert-ов по несколько тысяч в транзакции
2. Разделяешь создание запросов и их исполнение по разным thread, ибо первое — CPU, а второе IO bound.
3. Ждешь окончания транзакций и перестраиваешь индексы.
Пример кода ( под iPhone + немного страшен из-за некоторых попыток оптимизации )
github.com/dodikk/CsvToSqlite
Дерзай.
+1
>>Увы, не существует возможности открыть два соединения к одной и той же БД в памяти.
А по ссылке www.sqlite.org/inmemorydb.html в разделе «In-memory Databases And Shared Cache» написанно, что можно.
А по ссылке www.sqlite.org/inmemorydb.html в разделе «In-memory Databases And Shared Cache» написанно, что можно.
+1
Верно! Спасибо за информацию)
Не могу исправить в статье — получаю ошибку AJAX.
Увы, не существует возможности открыть два соединения к одной и той же БД в памяти.
UPD: Уже, оказывается, можно открыть два соединения к одной БД в памяти.
Не могу исправить в статье — получаю ошибку AJAX.
UPD: Уже, оказывается, можно открыть два соединения к одной БД в памяти.
rc = sqlite3_open("file:memdb1?mode=memory&cache=shared", &db);
ATTACH DATABASE 'file:memdb1?mode=memory&cache=shared' AS aux1;
0
Три раза в статье повторено, что нужно использовать только UTF-8. А можно пояснить — почему так?
+1
a) на текущий момент парсер только UTF-8 (не исключает факта, что в будущем появится парсер UTF-16);
b) UTF-8, как правило, быстрее (меньше данных пишется на диск);
c) база в памяти занимает меньше места.
b) UTF-8, как правило, быстрее (меньше данных пишется на диск);
c) база в памяти занимает меньше места.
0
Спасибо. Только не совсем понятен первый пункт — какой именно парсер? В статьях упоминания про него не нашел.
0
Много лет использую в SQLite кодировку windows-1251 вместо UTF-8. Никаких проблем с парсером это не создаёт. Но вот операции LIKE работают неправильно (не понимают регистр русских символов, конечно) и FTS-раширения тоже работают неправильно. Не стал переделывать collations, а вместо этого в FTS-индексах привожу всё к lowercase, и это снимает проблему.
0
Это означает, что целостность гарантирована при аварии приложения (поскольку ОС продолжает работать), но не при аварии ОС или отключении питания.
Режим синхронизации NORMAL (или 1) гарантирует целостность при авариях ОС и почти при всех отключениях питания. Существует ненулевой шанс, что при потере питания в самый неподходящий момент база испортится. Это некий средний, компромисный режим по производительности и надежности.
Режим FULL гарантирует целостность всегда и везде и при любых авариях. Но работает, разумеется, медленнее, поскольку в определенных местах делаются паузы ожидания. И это режим по умолчанию.
Блаженны верующие…
Режим FULL отличается от NORMAL только на макоси, где для FULL вызывается fnctl(fd, F_FULLFSYNC, ...) вместо fsync(). Для линукса всегда будет fdatasync, для винды — FlushFileBuffers. И ничего они не могут гарантировать, если диск или дисковый контроллер обманет. Хорошо (а, главное, честно) написано тут (ага, постгрес).
Учитывая вышесказанное, мне не очень понятно, что за смешные 50 транзакций в секунду. Постгрес выдает ~1000 (OpenVZ, Core2Duo E8400, HDD 7200RPM)
+1
Цифра взята отсюда: www.sqlite.org/faq.html#q19
Также сами разработчики утверждают, что в режиме FULL делаются дополнительные lock. Я не проверял этот факт. Разумеется, фраза про целостность всегда и везде содержит некоторую иронию. Мне казалось, что это заметно.
Также сами разработчики утверждают, что в режиме FULL делаются дополнительные lock. Я не проверял этот факт. Разумеется, фраза про целостность всегда и везде содержит некоторую иронию. Мне казалось, что это заметно.
0
Опять же сошлюсь на свой (и тысяч клиентов нашего софта!) многолетний опыт использования SQLite на серверах: SQLite все-таки изредка не справляется с сохранением целостности БД при сбоях питания или зависаниях железа (перегрев). Независимо от настроек синхронизации и режима журнала. Притом, что у нас он используется на Windows, где от NTFS ожидается дополнительная помощь в этом деле… Но увы. Не зря в SQLite есть backup API :)
+1
Все-таки, мне кажется, вы ошибаетесь насчет отличия FULL от NORMAL.
Комментарий из кода sqlite3.c:
Если поискать в коде места с «pPager->fullSync», то можно увидеть, что есть дополнительные операции в режиме FULL.
Комментарий из кода sqlite3.c:
/*
** CAPI3REF: Synchronization Type Flags
**
** When SQLite invokes the xSync() method of an
** [sqlite3_io_methods] object it uses a combination of
** these integer values as the second argument.
**
** When the SQLITE_SYNC_DATAONLY flag is used, it means that the
** sync operation only needs to flush data to mass storage. Inode
** information need not be flushed. If the lower four bits of the flag
** equal SQLITE_SYNC_NORMAL, that means to use normal fsync() semantics.
** If the lower four bits equal SQLITE_SYNC_FULL, that means
** to use Mac OS X style fullsync instead of fsync().
**
** Do not confuse the SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags
** with the [PRAGMA synchronous]=NORMAL and [PRAGMA synchronous]=FULL
** settings. The [synchronous pragma] determines when calls to the
** xSync VFS method occur and applies uniformly across all platforms.
** The SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags determine how
** energetic or rigorous or forceful the sync operations are and
** only make a difference on Mac OSX for the default SQLite code.
** (Third-party VFS implementations might also make the distinction
** between SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL, but among the
** operating systems natively supported by SQLite, only Mac OSX
** cares about the difference.)
*/
#define SQLITE_SYNC_NORMAL 0x00002
#define SQLITE_SYNC_FULL 0x00003
#define SQLITE_SYNC_DATAONLY 0x00010
Если поискать в коде места с «pPager->fullSync», то можно увидеть, что есть дополнительные операции в режиме FULL.
0
Нда, пожалуй, ошибаюсь (назовут все одинаково, сиди потом, грепай...), хотя это и не отменяет соображений насчет надежности fsync.
FULL от NORMAL отличается одной дополнительной синхронизацией журнала и выравниванием на следующий сектор при записи имени журнала. Т.е. оверхед относительно небольшой, и теоретически NORMAL и FULL тормозят примерно одинаково. Тогда, имхо, основная задержка возникает при записи самих данных (в постгресе синхронизируется только WAL, данные пишутся отдельным процессом в бекграунде).
В таком случае, в WAL режиме работать должно на порядок быстрее.
FULL от NORMAL отличается одной дополнительной синхронизацией журнала и выравниванием на следующий сектор при записи имени журнала. Т.е. оверхед относительно небольшой, и теоретически NORMAL и FULL тормозят примерно одинаково. Тогда, имхо, основная задержка возникает при записи самих данных (в постгресе синхронизируется только WAL, данные пишутся отдельным процессом в бекграунде).
В таком случае, в WAL режиме работать должно на порядок быстрее.
0
Ну, насчет «на порядок» не уверен) Но быстрее, да.
0
Да, WAL — оптимальный вариант, когда нужна приемлемая производительность без особого дрожания за целостность. Хотя в реализации WAL-режима в SQLite вплоть до текущих версий есть какая-то ошибка, из-за которой журнал иногда растёт больше заданного лимита (в многопоточном режиме использования). При этом всё продолжает работать без ошибок, но постепенно всё медленнее и медленнее, пока не переоткроешь БД в эксклюзивном режиме, тогда WAL записывается в основной файл, и всё нормализуется.
0
В столбец NONE значения заносятся «как есть» (этот тип используется по умолчанию, если не задан другой)Поверил, но оказалось не совсем так, если 64-битное число хранить в таком поле, то оно портится (INTEGER тоже не подходит), приходится использовать поле TEXT.
Вероятно тип NONE преобразуется автоматически к TEXT или INTEGER, в зависимости от содержимого.
0
Большое спасибо за пояснение WAL-режима человеческим языком, мне реально пригодилось при выяснении мелких нюансов для Delphi + FireDAC с 16+ одновременно пишущих thread-ов.
0
Sign up to leave a comment.
SQLite — замечательная встраиваемая БД (часть 3)