Каковы характеристики производительности sqlite с очень большими файлами базы данных?

289

Я знаю, что sqlite не очень хорошо работает с чрезвычайно большими файлами базы данных, даже когда они поддерживаются (на сайте sqlite был комментарий, в котором указано, что если вам нужны размеры файлов выше 1 ГБ, вы можете захотеть использовать предприятие rdbms. Не могу найти его больше, может быть связано с более старой версией sqlite).

Однако для моих целей я хотел бы получить представление о том, насколько это плохо, прежде чем я буду рассматривать другие решения.

Я говорю о файлах данных sqlite в диапазоне с несколькими гигабайтами, начиная с 2 ГБ. У кого-нибудь есть опыт? Любые советы/идеи?

  • 1
    Использование потоков (соединение на поток) может помочь только для чтения - stackoverflow.com/a/24029046/743263
Показать ещё 1 комментарий
Теги:
database
performance

9 ответов

201
Лучший ответ

Итак, я сделал несколько тестов с sqlite для очень больших файлов и сделал некоторые выводы (по крайней мере для моего конкретного приложения).

Тестирование включает в себя один файл sqlite с одной таблицей или несколькими таблицами. Каждая таблица имела около 8 столбцов, почти все целые числа и 4 индекса.

Идея заключалась в том, чтобы вставить достаточное количество данных, пока файлы sqlite не составят около 50 ГБ.

Отдельная таблица

Я попытался вставить несколько строк в файл sqlite только с одной таблицей. Когда файл был около 7 ГБ (извините, я не могу быть конкретным в отношении количества строк), вставки занимали слишком много времени. Я подсчитал, что мой тест на вставку всех моих данных займет около 24 часов, но он не завершился даже через 48 часов.

Это приводит меня к выводу, что одна, очень большая таблица sqlite будет иметь проблемы со вставками и, возможно, другие операции.

Я думаю, это не удивительно, поскольку таблица становится больше, вставка и обновление всех индексов занимает больше времени.

Несколько таблиц

Затем я попытался разделить данные по времени на несколько таблиц, по одной таблице в день. Данные для исходной 1 таблицы были разделены на ~ 700 таблиц.

У этой установки не было проблем с вставкой, она не занимала больше времени с течением времени, так как новая таблица была создана для каждого дня.

Вакуумные проблемы

Как указано i_like_caffeine, команда VACUUM является проблемой, тем больше файл sqlite. По мере того как будет выполнено больше вложений/удалений, фрагментация файла на диске будет ухудшаться, поэтому целью является периодическое VACUUM для оптимизации файла и восстановления файлового пространства.

Однако, как указано в документации, полная копия базы данных делается для того, чтобы сделать вакуум, потребовав очень много времени для завершения, Итак, чем меньше база данных, тем быстрее завершится эта операция.

Выводы

Для моего конкретного приложения я, вероятно, буду раскалывать данные по нескольким файлам db, по одному в день, чтобы получить максимум от производительности вакуума и скорости вставки/удаления.

Это усложняет запросы, но для меня это целесообразный компромисс, чтобы иметь возможность индексировать это много данных. Дополнительным преимуществом является то, что я могу просто удалить целый файл db, чтобы удалить данные за день (общая операция для моего приложения).

Мне, вероятно, придется контролировать размер таблицы для каждого файла, чтобы увидеть, когда скорость станет проблемой.

Слишком плохо, что не существует дополнительного метода вакуума, кроме автоматического вакуума. Я не могу использовать его, потому что моя цель для вакуума - дефрагментировать файл (файловое пространство не является большим делом), которого автоматический вакуум не делает. Фактически, документация утверждает, что это может сделать фрагментацию еще хуже, поэтому мне приходится прибегать к периодическому полному вакууму в файле.

  • 5
    Очень полезная информация Чистое предположение, но мне интересно, можно ли использовать новый API резервного копирования для ежедневного создания нефрагментированной версии базы данных и избежать необходимости запуска VACUUM.
  • 21
    Мне любопытно, были ли все ваши ВСТАВКИ в транзакции?
Показать ещё 7 комментариев
138

Мы используем DBS 50 GB + на нашей платформе. никаких жалоб не работает. Убедитесь, что вы все делаете правильно! Вы используете предопределенные заявления? * SQLITE 3.7.3

  • Сделки
  • Предварительно сделанные заявления
  • Примените эти настройки (сразу после создания БД)

    PRAGMA main.page_size = 4096;
    PRAGMA main.cache_size=10000;
    PRAGMA main.locking_mode=EXCLUSIVE;
    PRAGMA main.synchronous=NORMAL;
    PRAGMA main.journal_mode=WAL;
    PRAGMA main.cache_size=5000;
    

Надеюсь, это поможет другим, отлично работает здесь.

  • 20
    Недавно протестирован с БД в диапазоне 160 ГБ, также отлично работает.
  • 8
    Также PRAGMA main.temp_store = MEMORY; ,
Показать ещё 6 комментариев
55

Я создал базы данных SQLite размером до 3,5 ГБ без заметных проблем с производительностью. Если я правильно помню, я думаю, что SQLite2 мог иметь некоторые более низкие пределы, но я не думаю, что SQLite3 имеет такие проблемы.

В соответствии с страницами SQLite Limits максимальный размер каждой страницы базы данных составляет 32K. Максимальные страницы в базе данных - 1024 ^ 3. Так по моей математике, которая достигает 32 терабайт как максимальный размер. Я думаю, вы попадете в пределы вашей файловой системы, прежде чем ударить SQLite!

  • 1
    В зависимости от того, какие операции вы выполняете, пытаясь удалить 3000 строк в базе данных sqlite 8G, вам потребуется достаточно времени, чтобы приготовить хороший горшок с французской прессой, смеется
43

Большая часть причин, по которым потребовалось более 48 часов, чтобы сделать ваши вставки, объясняется вашими индексами. Это невероятно быстрее:

1 - Отбросьте все индексы 2 - Сделайте все вставки 3 - Создание индексов снова

  • 21
    Это хорошо известно ... но для длительного процесса вы не будете периодически отбрасывать свои индексы, чтобы перестраивать их, особенно когда вы будете запрашивать их для выполнения работы. Такой подход используется, хотя, когда sqlite db нужно перестраивать с нуля, индексы создаются после того, как все вставки сделаны.
  • 24
    В аналогичной ситуации @Snazzer мы использовали таблицу «аккумулятор»: один раз в день мы перемещали накопленные строки из таблицы аккумуляторов в основную таблицу в рамках одной транзакции. Там, где это было необходимо, представление позаботилось о представлении обеих таблиц как одной таблицы.
Показать ещё 3 комментария
27

Кроме обычной рекомендации:

  • Индекс падения для массовой вставки.
  • Пакетные вставки/обновления в больших транзакциях.
  • Настройте буферный кеш/отключите журнал /w PRAGMA.
  • Используйте 64-битную машину (чтобы использовать много кеш-памяти).
  • [добавлен июль 2014] Используйте общее табличное выражение (CTE) вместо запуска нескольких SQL-запросов! Требуется выпуск SQLite 3.8.3.

Из моего опыта работы с SQLite3 я узнал следующее:

  • Для максимальной скорости вставки не используйте схему с любым ограничением столбца. ( Изменить таблицу позже по мере необходимости Вы не можете добавлять ограничения с помощью ALTER TABLE).
  • Оптимизируйте свою схему, чтобы сохранить то, что вам нужно. Иногда это означает разбиение таблиц и/или даже сжатие/преобразование ваших данных перед вставкой в ​​базу данных. Отличным примером является сохранение IP-адресов в виде (длинных) целых чисел.
  • Одна таблица на файл db - чтобы минимизировать конфликт блокировок. (Используйте ATTACH DATABASE, если вы хотите иметь один объект подключения.
  • SQLite может хранить разные типы данных в одном столбце (динамическая типизация), использовать это в ваших интересах.

Вопрос/комментарий.; -)

  • 1
    Какое влияние вы получаете от «одной таблицы на файл БД»? Звучит интересно. Как вы думаете, это будет иметь большое значение, если ваша таблица имеет только 3 таблицы и строится с нуля?
  • 3
    @martin ненавижу это говорить, но ответ - это зависит . Идея состоит в том, чтобы разделить данные до управляемого размера. В моем случае использования я собираю данные с разных хостов и готовлю отчеты по фактам, чтобы этот подход работал хорошо. Разделение по дате / времени, как предлагают другие, должно хорошо работать для данных, которые охватывают длительный период времени, который я себе представляю.
Показать ещё 3 комментария
8

Я думаю, что основные жалобы на масштабирование sqlite:

  • Отдельная запись процесса.
  • Нет зеркального отображения.
  • Нет репликации.
7

У меня есть база данных SQLite объемом 7 ГБ. Для выполнения конкретного запроса с внутренним соединением требуется 2.6 Чтобы ускорить это, я попытался добавить индексы. В зависимости от того, какие индексы я добавил, иногда запрос опускался до 0,1 с, а иногда он увеличивался до 7 с. Я думаю, что проблема в моем случае заключалась в том, что если столбец сильно дублируется, то добавление индекса ухудшает производительность: (

  • 9
    Почему столбец с множеством дубликатов может ухудшить производительность (серьезный вопрос)?
  • 6
    труднее проиндексировать столбец с низким количеством элементов: stackoverflow.com/questions/2113181/…
6

В документации SQLite раньше указывалось, что практический размер файла базы данных составляет несколько десятков ГБ: с. В основном это связано с необходимостью SQLite "распределять битмап грязных страниц" всякий раз, когда вы начали транзакцию. Таким образом, 256 байт ОЗУ были необходимы для каждого МБ в базе данных. Вставка в DB файл объемом 50 ГБ потребует массивного (2 ^ 8) * (2 ^ 10) = 2 ^ 18 = 256 МБ ОЗУ.

Но по последним версиям SQLite это больше не требуется. Подробнее здесь.

  • 24
    Мне очень жаль, что я должен указать на это, но 2^18 на самом деле только 256 К.
  • 7
    @GabrielSchreiber, а также тот факт, что 50 ГБ - это не (2 ^ 10) МБ, это всего лишь 1 ГБ. Таким образом, для базы данных объемом 50 ГБ требуется 12,5 МБ памяти: (2 ^ 8) * (2 ^ 10) * 50
6

У меня возникли проблемы с большими файлами sqlite при использовании команды вакуума.

Я еще не пробовал функцию auto_vacuum. Если вы планируете регулярно обновлять и удалять данные, то это стоит посмотреть.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню