RAM'de Yaşayan Bir Veritabanı
SQLite'ın özel bir dosya adı vardır: :memory:. Bir veritabanını bu isimle açtığınızda SQLite diske hiç dokunmaz — veritabanının tamamı RAM'de tutulur. Tablolar, indeksler, transaction'lar, foreign key'ler... her özellik birebir aynı şekilde çalışır. Tek fark şu: bağlantıyı kapattığınız anda veritabanı buharlaşır.
Komut satırından kullanımı şöyle:
sqlite3 :memory:
Artık SQLite komut isteminde, yalnızca bellekte yaşayan bambaşka boş bir veritabanıyla karşı karşıyasın. Tablo oluştur, birkaç satır ekle, sorgula — her şey normal akışında:
Oturumu kapattığınız anda o veriler buharlaşır. Geride bir dosya kalmaz, çünkü hiçbir zaman bir dosya oluşturulmamıştır.
Neden İhtiyaç Duyarsınız?
Yeniden başlatmaya dayanamayan bir veritabanı kulağa özellik gibi değil, hata gibi geliyor. Ama aslında üç durumda epey işe yarıyor.
Testler. Her test milisaniyeler içinde tertemiz bir veritabanıyla başlar. Geçici dosya temizliği yok, önceki koşumdan kalma artık veri yok, kilitlenen ortak fixture dosyası yok. Python, Node ve Go'daki SQLite kullanan test paketlerinin çoğu tam da bu yüzden :memory: ile çalışır.
Tek seferlik analiz. Bir CSV yükleyin, birkaç sorgu çalıştırın, sonra at gitsin. Gerçek bir veritabanı ayağa kaldırmaktan hızlı, dosyayı her seferinde kodla parse etmekten kolay.
Önbellek ve karalama alanı. Uzun süre çalışan bir programın içinde, daha önce belleğe yüklediğiniz veriler için bellekte tutulan bir SQLite veritabanı şaşırtıcı derecede iyi bir geçici sorgu motoru olabiliyor.
Ortak nokta şu: SQL istiyorsunuz ama kalıcılık istemiyorsunuz.
Performans: Daha Hızlı, Ama Sihirli Değil
sqlite in memory database, diski tamamen atladığı için normalde dosya sistemine giden yazma işlemleri sadece bellek güncellemesine dönüşür. I/O'ya takılan iş yükleri belirgin şekilde hızlanır. CPU'ya takılan iş yükleri — karmaşık sorgu planlama, büyük sıralamalar — neredeyse hiç değişmez; çünkü SQLite zaten sık kullanılan sayfaları bellekte önbelleğe alıyordu.
Söz dizimi açısından ne kadar aynı olduğunu göstermek için kısa bir örnek:
Bu örnek bellekte (in-memory) bir veritabanına karşı çalıştı ama aynı SQL'i bir dosyaya karşı da rahatlıkla çalıştırabilirdin. Veritabanı motoru için fark etmiyor.
SQLite memory vs file: Hangisini ne zaman seçmeli?
Aradaki fark aslında çok net, ama yine de açıkça yazmakta fayda var:
- Dosya veritabanı (
mydata.db): Yeniden başlatmalardan etkilenmez, veriler kalıcıdır. Birden fazla süreç aynı anda açabilir. Çökmelerde de büyük ölçüde ayakta kalır (özellikle WAL modunda). Bir şeyleri hatırlaması gereken her durumda bunu kullan. - Bellekte veritabanı (
:memory:): Bağlantı kapandığı anda uçup gider. Varsayılan olarak yalnızca onu açan bağlantıya özeldir. Yazma yoğun, kullan-at işler için daha hızlıdır. Testler, geçici denemeler ve kısa ömürlü önbellekler için biçilmiş kaftan.
Kararsız kaldıysan büyük ihtimalle dosyayı istiyorsundur. In-memory, özel durum olanıdır.
Her bağlantının kendi belleği var
İnsanları sıkça tuzağa düşüren ince bir nokta: :memory: ifadesini iki kez açtığında elinizde iki ayrı veritabanı olur. Aynı tabloları paylaşmazlar, aynı veriye erişmezler, birbirlerinden tamamen habersizdirler.
-- Terminal 1
sqlite3 :memory:
sqlite> CREATE TABLE t (x); INSERT INTO t VALUES (1);
-- Terminal 2
sqlite3 :memory:
sqlite> SELECT * FROM t;
Error: no such table: t
Bu bir hata değil — tasarımın ta kendisi. :memory: aslında "bu bağlantıya özel bir veritabanı" demek. Aynı şey tek bir program içinde de geçerli: kodunuz :memory: ile iki bağlantı açarsa, her biri kendi izole veritabanını alır.
Bellekteki Veritabanını Birden Fazla Bağlantıyla Paylaşmak
Aynı bellek içi veritabanını birden çok bağlantının görmesi gerekiyorsa, SQLite bunu URI biçimindeki dosya adları ve paylaşımlı önbellek (shared cache) üzerinden destekler. Sihirli ifade şu: file::memory:?cache=shared:
sqlite3 'file::memory:?cache=shared'
Aynı süreç içinde bu URI'yi açan tüm bağlantılar aynı veritabanını paylaşır. Hepsini kapattığınız anda veritabanı uçup gider.
Birden fazla farklı paylaşımlı veritabanına ihtiyacınız olduğunda, bellekteki veritabanına bir isim de verebilirsiniz:
sqlite3 'file:mydb?mode=memory&cache=shared'
Buradaki mydb ismi sadece bir etiket — ortada hâlâ bir dosya yok. file:mydb?mode=memory&cache=shared ile açılan iki bağlantı aynı veritabanını paylaşır; file:other?mode=memory&cache=shared ile açılan bir bağlantı ise bambaşka bir veritabanı alır.
SQLite in-memory veritabanını diske kaydetme
Bazen tüm işi bellekte yapıp ardından sonucu saklamak istersiniz. CLI'nin tam da bunun için bir .backup nokta komutu var:
sqlite3 :memory:
sqlite> CREATE TABLE results (id INTEGER, score REAL);
sqlite> INSERT INTO results VALUES (1, 0.91), (2, 0.87);
sqlite> .backup snapshot.db
sqlite> .quit
snapshot.db artık aynı içeriğe sahip, sıradan bir dosya veritabanı oldu. Daha sonra sqlite3 snapshot.db komutuyla açıp kaldığınız yerden devam edebilirsiniz.
Tersi de mümkün — .restore komutu, bir dosya veritabanını mevcut bağlantının belleğine yükler:
sqlite3 :memory:
sqlite> .restore snapshot.db
sqlite> SELECT * FROM results;
Uygulama tarafında SQLite C API'si sqlite3_backup_init ile aynı mekanizmayı sunar ve dil bağlamalarının çoğu bunun üzerine bir sarmalayıcı (wrapper) sağlar. Örneğin Python'un sqlite3 modülünde Connection.backup() metodu bu işi görür.
Sıkça Yapılan Bir Hata
Bazen bellekteki veritabanını "kaydetmek" için bir dosya attach edip içeriği kopyalamaya çalışıldığını görüyoruz:
Bu yöntem basit tablo kopyaları için iş görür, ama indeksleri, trigger'ları, view'ları veya foreign key'leri olduğu gibi taşımaz. Bütün bir veritabanının birebir kopyasını almak istiyorsanız .backup komutunu (veya backup API'sini) kullanın — sayfa seviyesinde, ikili olarak birebir kopya çıkarır.
Özetle Aklında Kalsın
:memory:, SQLite'a özel bir dosya adıdır; arkasında dosya olmadan, doğrudan RAM'de bir veritabanı oluşturur.- SQL tarafı dosya tabanlı veritabanıyla bire bir aynıdır — aynı tablolar, aynı sorgular, aynı kısıtlamalar.
:memory:ile kurulan her bağlantı kendine özeldir; birden fazla bağlantının aynı veritabanını paylaşması gerekiyorsa shared-cache URI'lerini (file::memory:?cache=shared) kullanın.- Testler, tek seferlik analizler ve kısa ömürlü önbellekler için biçilmiş kaftandır — yeniden başlatmaya dayanması gereken hiçbir şey için uygun değildir.
- Bellekteki veritabanını saklamaya karar verdiğinizde,
.backupile diske terfi ettirebilirsiniz.
Sırada: Tablo Oluşturma
Şimdiye kadar birkaç örnekte CREATE TABLE'ı şöyle bir gördünüz. Bir sonraki sayfada hız kesip işin detayına ineceğiz — kolon tanımları, veri tipleri, ekleyebileceğiniz kısıtlamalar ve şemanızla rahatça yaşamanızı sağlayacak küçük tercihler.
Sıkça Sorulan Sorular
SQLite in-memory database nasıl oluşturulur?
Dosya yolu yerine özel :memory: adını kullanarak SQLite'ı açmanız yeterli. Komut satırında sqlite3 :memory: yazıyorsunuz; bir kütüphane kullanıyorsanız da connect çağrısına dosya adı olarak :memory: veriyorsunuz. Veritabanı tamamen RAM'de yaşar ve bağlantı kapandığında uçar gider.
SQLite'ta :memory: ne demek?
:memory:, SQLite'ın 'dosya kullanma, her şeyi RAM'de tut' olarak yorumladığı özel bir dosya adıdır. Karşılığında tam bir SQLite veritabanı elde edersiniz — tablolar, indeksler, transaction'lar, hepsi var — ama hiçbir şey diske yazılmaz. :memory: ile açılan her bağlantı kendine ait, izole bir veritabanına sahip olur.
İki bağlantı aynı in-memory SQLite veritabanını paylaşabilir mi?
Varsayılan olarak hayır — her :memory: bağlantısı birbirinden izoledir. Paylaşmak istiyorsanız file::memory:?cache=shared gibi bir URI ile açıp shared cache'i etkinleştirmeniz gerekiyor. Aynı süreç içinde bu URI'yi açan tüm bağlantılar aynı veritabanını görür.
In-memory SQLite veritabanı diske kaydedilebilir mi?
Evet. Komut satırında .backup komutunu, kütüphane tarafında ise backup API'sini kullanarak RAM'deki veritabanını bir dosyaya kopyalayabilirsiniz. Alternatif olarak bir dosya veritabanını ATTACH ile bağlayıp INSERT INTO file.table SELECT * FROM main.table ile veriyi taşıyabilirsiniz.