SQLite
 sql >> база данни >  >> RDS >> SQLite

Настройка на производителността на SQLite

SQLite е популярна релационна база данни, която вграждате във вашето приложение. С нарастващо количество данни във вашата база данни, трябва да приложите настройка на производителността на SQLite. Тази статия обсъжда индексите и техните клопки, използването на планировщика на заявки, режима на дневник за записване напред (WAL) и увеличаването на размера на кеша. Той също така разяснява важността на измерването на въздействието на вашите настройки чрез автоматизирани тестове.

Въведение

SQLite е популярна система за релационна база данни (DB) . За разлика от по-големите си братя, базирани на клиент-сървър, като MySQL, SQLite може да бъде вграден във вашето приложение като библиотека . SQLite има много подобен набор от функции и може да обработва милиони редове, като се има предвид, че знаете няколко съвета и трика за настройката на производителността. Както ще покажат следващите раздели, има да знаете повече за настройката на производителността на SQLite, отколкото просто създаването на индекси.

Създавайте индекси, но с повишено внимание

Основната идея на индекса е да ускори четенето на конкретни данни , тоест SELECT изрази с WHERE клауза. Индексите също ускоряватсортирането даннита (ORDER BY ), или JOIN инг таблици. За съжаление индексите са нож с две остриета, защото консумират допълнително дисково пространство и забавят манипулирането на данни (INSERT , UPDATE , DELETE ).

Основният съвет е да създавате възможно най-малко индекси, но колкото е необходимо . Освен това индексите имат смисъл само за по-големи бази данни, с хиляди или милиони редове.

Използвайте инструмента за планиране на заявки, за да анализирате заявките си

Начинът, по който индексите се използват вътрешно от SQLite, е документиран, но не е много лесен за разбиране. Както е по-подробно обяснено в тази статия, добра идея е да анализирате заявка, като й поставите префикс с EXPLAIN QUERY PLAN . Разгледайте всеки изходен ред, от който има три основни варианта:

  • SEARCH table ... линиите са добър знак – SQLite използва един от вашите индекси!
  • SCAN table ... USING INDEX е лош знак,
  • SCAN table ... е още по-лошо!

Опитайте се да избягвате SCAN table [using index] записи в изхода на EXPLAIN QUERY PLAN когато е възможно, защото ще срещнете проблеми с производителността на по-големи бази данни. Използвайте EXPLAIN QUERY PLAN за итеративно добавяне или промяна на вашите индекси, докато престане SCAN table се появяват записи.

Оптимизирайте заявки, които включват IS NOT

Проверка за IS NOT ... е скъпо защото SQLite ще трябва да сканира всички редове на таблицата, дори ако засегнатата колона има индекс . Индексите са полезни само ако търсите конкретни стойности, т.е. сравнения, включващи < (по-малък), > (по-голям) или = (равно), но не се прилагат за !=(неравно).

Един чист малък трик е, че можете да замените WHERE column != value с WHERE column > value OR column < value . Това ще използва индекса на колоната и ефективно ще засегне всички редове, чиято стойност не е равна на value . По същия начин, WHERE stringColumn != '' може да бъде заменен с WHERE stringColumn > '' , защото низовете са сортируеми. Когато прилагате този трик обаче, уверете се, че знаете как SQLite обработва NULL сравнения. Например SQLite оценява NULL > '' като FALSE .

Ако използвате такъв трик за сравнение, има още едно предупреждение, в случай че заявката ви съдържа WHERE и ORDER BY , всяка с различна колона:това отново ще направи заявката неефективна. Ако е възможно, използвайте същото колона в WHERE и ORDER BY , или създайте покриващ индекс което включва и двете WHERE и ORDER BY колона.

Подобрете скоростта на запис с Write-Ahead-Log

Регистриране с предварителна запис (WAL) режимът на журнал значително подобрява производителността на запис/актуализацията , в сравнение с връщане назад по подразбиране режим на дневник. Въпреки това, както е документирано тук, има няколко предупреждения . Например режимът WAL не е наличен за определени операционни системи. Освен това има намалени гаранции за последователност на данните в случай на повреда на хардуера . Не забравяйте да прочетете първите няколко страници, за да разберете какво правите.

Открих, че командата PRAGMA synchronous = NORMAL осигурява 3-4x ускорение. Настройка на journal_mode към WAL след това отново значително подобрява производителността (приблизително 10 пъти или повече, в зависимост от операционната система).

Освен предупрежденията, които вече споменах, трябва да сте наясно и със следното:

  • Използвайки режима на дневник WAL, ще има два допълнителни файла до файла на базата данни във вашата файлова система, които имат същото име като базата данни, но суфикси „-shm“ и „-wal“. Обикновено не е нужно да ви пука, но ако трябва да изпратите базата данни на друга машина, докато приложението ви работи, не забравяйте да включите тези два файла. SQLite ще уплътни тези два файла в основния файл всеки път, когато обикновено затваряте всички отворени връзки към базата данни.
  • Ефективността на вмъкване или актуализиране ще намалява от време на време, когато заявката задейства сливането на съдържанието на регистрационния файл на WAL в основния файл на базата данни. Това се нарича контролна точка , вижте тук.
  • Намерих тази PRAGMA които променят journal_mode и synchronous изглежда не се съхраняват постоянно в базата данни. Така аз винаги да ги изпълнявам отново всеки път, когато отворя нова връзка с базата данни, вместо просто да ги изпълнявам, когато създавам таблиците за първи път.

Измерете всичко

Всеки път, когато добавяте промени в производителността, не забравяйте да измервате въздействието. Автоматизираните (единични) тестове са чудесен подход за това. Те помагат за документиране вашите открития за вашия екип и те ще разкрият отклоняващо се поведение с течение на времетота , напр. когато актуализирате до по-нова версия на SQLite. Примери за това, което можете да измерите:

  • Какъв е ефектът от използването на WAL режим на дневник над връщане назад режим? Какъв е ефектът от друга (предполагаемо) подобряваща производителността PRAGMA s?
  • След като добавите/промените/премахнете индекс, колко по-бързо ще направите SELECT изявления стават? Колко по-бавно работи INSERT/DELETE/UPDATE изявленията стават?
  • Колко допълнително дисково пространство заемат индексите?

За всеки от тези тестове помислете за повторението им с различни размери на базата данни. напр. стартирайте ги в празна база данни, а също и в база данни, която вече съдържа хиляди (или милиони) записи. Също така трябва да изпълните тестовете на различни устройства и операционни системи, особено ако вашата среда за разработка и производство се различават значително.

Настройте размера на кеша

SQLite съхранява временна информация в кеш (в RAM), напр. докато изграждате резултатите от SELECT заявка, или при манипулиране на данни, които все още не са били ангажирани. По подразбиране този размер е мизерните 2 MB . Съвременните настолни машини могат да спестят много повече. Изпълнете PRAGMA cache_size = -kibibytes за да увеличите тази стойноста (имайте предвид минус знак пред стойността!). Вижте тук за допълнителна информация. Отново измерете какво влияние оказва тази настройка върху производителността!

Използвайте REPLACE INTO, за да създадете или актуализирате ред

Това може да не е толкова ощипване на производителността, колкото е чист малък трик. Да предположим, че трябва да актуализирате ред в таблица t , или създайте ред, ако все още не съществува. Вместо да използвате две заявки (SELECT последвано от INSERT или UPDATE ), използвайте REPLACE INTO (официални документи).

За да работи това, добавете допълнителна фиктивна колона (напр. replacer ) към таблица t , който има UNIQUE ограничавам. Декларацията на колоната може напр. бъде ... replacer INTEGER UNIQUE ... това е част от вашия CREATE TABLE изявление. След това използвайте заявка като

REPLACE INTO t (col1, col2, ..., replacer) VALUES (?,?,...,1)Code language: SQL (Structured Query Language) (sql)

Когато тази заявка се изпълнява за първи път, тя просто ще извърши INSERT . Когато се стартира втори път, UNIQUE ограничение на replacer колона ще се задейства и поведението за разрешаване на конфликти ще доведе до отпадане на стария ред, създавайки автоматично нов. Може също да намерите свързаната команда UPSERT за полезна.

Заключение

След като броят на редовете във вашата база данни нарасне, промените в производителността стават необходимост. Индексите са най-често срещаното решение. Те обменят подобрена времева сложност за намалена сложност на пространството, подобрявайки скоростта на четене, като същевременно влияят негативно на производителността при модифициране на данни. А, демонстрирах, трябва да бъдете особено внимателни, когато сравнявате за неравенство в SELECT изрази, тъй като SQLite не може да използва индекси за подобни видове сравнения. Обикновено препоръчвам да използвате планировщика на заявки това обяснява какво се случва вътрешно за всяка SQL заявка. Всеки път, когато настройвате нещо, измервайте въздействието!


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Трябва ли да създам клас, който наследява SQLiteOpenHelper за всяка таблица в моята база данни?

  2. Върнете края на месеца в SQLite

  3. Грешка на SQLiteConstraintException се показва след стартиране на всяка дейност

  4. Наличие на SQLite

  5. Как да инсталирате най-новата версия на Sqlite aar, когато използвате Room On Android