SQLite
 sql >> Teknologi Basis Data >  >> RDS >> SQLite

Penyetelan kinerja SQLite

SQLite adalah database relasional populer yang Anda sematkan ke dalam aplikasi Anda. Dengan peningkatan jumlah data dalam database Anda, Anda perlu menerapkan penyetelan kinerja SQLite. Artikel ini membahas indeks dan perangkapnya, penggunaan perencana kueri, mode jurnal Write-Ahead-Logging (WAL) dan peningkatan ukuran cache. Ini juga menjelaskan tentang pentingnya mengukur dampak tweak Anda, menggunakan pengujian otomatis.

Pengantar

SQLite adalah sistem database relasional (DB) yang populer . Tidak seperti saudaranya yang lebih besar, berbasis client-server, seperti MySQL, SQLite dapat disematkan ke dalam aplikasi Anda sebagai perpustakaan . SQLite memiliki kumpulan fitur yang sangat mirip dan juga dapat menangani jutaan baris, mengingat Anda mengetahui beberapa tip dan trik tentang penyetelan kinerja. Seperti yang akan ditunjukkan pada bagian berikut, ada lebih banyak yang perlu diketahui tentang penyetelan kinerja SQLite daripada hanya membuat indeks.

Buat indeks, tetapi dengan hati-hati

Ide dasar indeks adalah untuk mempercepat membaca data tertentu , yaitu, SELECT pernyataan dengan WHERE ayat. Indeks juga mempercepat penyortiran data (ORDER BY ), atau JOIN tabel. Sayangnya, indeks adalah pedang bermata dua, karena menggunakan ruang disk tambahan dan memperlambat manipulasi data (INSERT , UPDATE , DELETE ).

Saran umum adalah membuat indeks sesedikit mungkin, tetapi sebanyak yang diperlukan . Juga, indeks hanya masuk akal untuk lebih besar database, dengan ribuan atau jutaan baris.

Gunakan perencana kueri untuk menganalisis kueri Anda

Cara indeks digunakan secara internal oleh SQLite didokumentasikan, tetapi tidak terlalu mudah untuk dipahami. Sebagaimana diuraikan lebih lanjut oleh artikel ini, sebaiknya menganalisis kueri dengan mengawalinya dengan EXPLAIN QUERY PLAN . Lihatlah setiap jalur keluaran, di mana ada tiga varian dasar:

  • SEARCH table ... garis adalah pertanda baik – SQLite menggunakan salah satu indeks Anda!
  • SCAN table ... USING INDEX pertanda buruk,
  • SCAN table ... bahkan lebih buruk!

Cobalah untuk menghindari SCAN table [using index] entri dalam output EXPLAIN QUERY PLAN bila memungkinkan, karena Anda akan mengalami masalah kinerja pada database yang lebih besar. Gunakan EXPLAIN QUERY PLAN untuk iteratif tambahkan atau ubah indeks Anda sampai tidak ada lagi SCAN table entri muncul.

Optimalkan kueri yang melibatkan IS NOT

Memeriksa IS NOT ... mahal karena SQLite harus memindai semua baris tabel, bahkan jika kolom yang terpengaruh memiliki indeks . Indeks hanya berguna jika Anda mencari nilai tertentu, yaitu perbandingan yang melibatkan (lebih kecil), > (lebih besar), atau = (sama), tetapi tidak berlaku untuk !=(tidak sama).

Trik kecil yang rapi adalah Anda dapat mengganti WHERE column != value dengan WHERE column > value OR column < value . Ini akan menggunakan indeks kolom dan secara efektif mempengaruhi semua baris yang nilainya tidak sama dengan value . Demikian pula, sebuah WHERE stringColumn != '' dapat diganti dengan WHERE stringColumn > '' , karena string dapat diurutkan. Namun, saat menerapkan trik ini, pastikan Anda mengetahui cara SQLite menangani NULL perbandingan. Misalnya, SQLite mengevaluasi NULL > '' sebagai FALSE .

Jika Anda menggunakan trik perbandingan seperti itu, ada peringatan lain jika kueri Anda berisi WHERE dan ORDER BY , masing-masing dengan kolom yang berbeda:ini akan membuat kueri menjadi tidak efisien lagi. Jika memungkinkan, gunakan sama kolom di WHERE dan ORDER BY , atau buat indeks penutup yang melibatkan keduanya WHERE dan ORDER BY kolom.

Tingkatkan kecepatan tulis dengan Write-Ahead-Log

The Write-Ahead-Logging (WAL) mode jurnal secara signifikan meningkatkan kinerja tulis/perbarui , dibandingkan dengan putar balik default default modus jurnal. Namun, seperti yang didokumentasikan di sini, ada beberapa peringatan . Misalnya, mode WAL tidak tersedia pada sistem operasi tertentu. Selain itu, ada jaminan konsistensi data yang berkurang jika terjadi kegagalan perangkat keras . Pastikan untuk membaca beberapa halaman pertama untuk memahami apa yang Anda lakukan.

Saya menemukan bahwa perintah PRAGMA synchronous = NORMAL memberikan percepatan 3-4x. Menyetel journal_mode ke WAL kemudian meningkatkan kinerja lagi secara signifikan (sekitar 10x atau lebih, tergantung pada sistem operasinya).

Selain peringatan yang telah saya sebutkan, Anda juga harus mengetahui hal-hal berikut:

  • Dengan menggunakan mode jurnal WAL, akan ada dua file tambahan di sebelah file database pada sistem file Anda, yang memiliki nama yang sama dengan database, tetapi diberi akhiran “-shm” dan “-wal”. Biasanya Anda tidak perlu peduli, tetapi jika Anda ingin mengirim database ke komputer lain saat aplikasi Anda sedang berjalan, jangan lupa untuk menyertakan kedua file tersebut. SQLite akan memadatkan kedua file ini ke dalam file utama setiap kali Anda biasanya menutup semua koneksi database yang terbuka.
  • Kinerja penyisipan atau pembaruan akan turun sesekali, setiap kali kueri memicu penggabungan konten file log WAL ke dalam file database utama. Ini disebut pos pemeriksaan , lihat di sini.
  • Saya menemukan bahwa PRAGMA s yang mengubah journal_mode dan synchronous tampaknya tidak terus-menerus disimpan dalam database. Jadi, saya selalu jalankan kembali setiap kali saya membuka koneksi database baru, daripada hanya menjalankannya saat membuat tabel untuk pertama kalinya.

Ukur semuanya

Setiap kali Anda menambahkan penyesuaian kinerja, pastikan untuk mengukur dampaknya. Pengujian (unit) otomatis adalah pendekatan yang bagus untuk ini. Mereka membantu mendokumentasikan temuan Anda untuk tim Anda, dan mereka akan mengungkap perilaku menyimpang dari waktu ke waktu , misalnya saat Anda memperbarui ke versi SQLite yang lebih baru. Contoh untuk apa yang dapat Anda ukur:

  • Apa efek menggunakan WAL mode jurnal melalui rollback mode? Apa efek dari PRAGMA peningkatan kinerja lainnya (seharusnya) s?
  • Setelah Anda menambah/mengubah/menghapus indeks, seberapa cepat SELECT pernyataan menjadi? Seberapa lambat INSERT/DELETE/UPDATE pernyataan menjadi?
  • Berapa banyak ruang disk tambahan yang digunakan indeks?

Untuk salah satu pengujian ini, pertimbangkan untuk mengulanginya dengan berbagai ukuran database. Misalnya. jalankan di database kosong, dan juga di database yang sudah berisi ribuan (atau jutaan) entri. Anda juga harus menjalankan pengujian pada perangkat dan sistem operasi yang berbeda, terutama jika lingkungan pengembangan dan produksi Anda sangat berbeda.

Sesuaikan ukuran cache

SQLite menyimpan informasi sementara dalam cache (dalam RAM), mis. sambil membangun hasil SELECT query, atau ketika memanipulasi data yang belum di-commit. Secara default, ukuran ini hanya 2 MB . Mesin desktop modern dapat menghemat lebih banyak. Jalankan PRAGMA cache_size = -kibibytes untuk meningkatkan nilai ini (ingat minus tanda di depan nilainya!). Lihat di sini untuk informasi lebih lanjut. Sekali lagi, ukur apa pengaruh setelan ini terhadap performa!

Gunakan REPLACE INTO untuk membuat atau memperbarui baris

Ini mungkin bukan tweak kinerja karena ini adalah trik kecil yang rapi. Misalkan Anda perlu memperbarui baris dalam tabel t , atau buat baris jika belum ada. Daripada menggunakan dua kueri (SELECT diikuti dengan INSERT atau UPDATE ), gunakan REPLACE INTO (dokumen resmi).

Agar ini berfungsi, tambahkan kolom dummy tambahan (mis. replacer ) ke tabel t , yang memiliki UNIQUE memaksa. Deklarasi kolom dapat mis. menjadi ... replacer INTEGER UNIQUE ... itu adalah bagian dari CREATE TABLE . Anda penyataan. Kemudian gunakan kueri seperti

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

Saat kueri ini dijalankan untuk pertama kalinya, ia hanya akan melakukan INSERT . Saat dijalankan kedua kalinya, UNIQUE batasan replacer kolom akan dipicu, dan perilaku resolusi konflik akan menyebabkan baris lama dihapus, membuat yang baru secara otomatis. Anda mungkin juga menemukan bahwa perintah UPSERT terkait berguna.

Kesimpulan

Setelah jumlah baris dalam database Anda bertambah, penyesuaian kinerja menjadi suatu keharusan. Indeks adalah solusi yang paling umum. Mereka memperdagangkan peningkatan kompleksitas waktu untuk mengurangi kompleksitas ruang, meningkatkan kecepatan baca, sementara secara negatif mempengaruhi kinerja modifikasi data. A sudah saya tunjukkan, Anda harus ekstra hati-hati saat membandingkan ketidaksetaraan di SELECT pernyataan, karena SQLite tidak dapat menggunakan indeks untuk jenis perbandingan seperti itu. Saya biasanya merekomendasikan menggunakan perencana kueri yang menjelaskan apa yang terjadi secara internal untuk setiap kueri SQL. Setiap kali Anda mengubah sesuatu, ukur dampaknya!


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Grup SQLite berdasarkan/hitung jam, hari, minggu, tahun

  2. Bagaimana cara menggunakan Perpustakaan Persistensi Kamar dengan basis data yang sudah diisi sebelumnya?

  3. Pilihan SQLite

  4. SQLite - Buat Basis Data

  5. Mengapa saya mendapatkan java.lang.IllegalArgumentException:nilai pengikatan pada indeks 1 adalah nol dalam kasus ini?