Isar Plus

İndeksler

Güçlü indeks stratejileriyle sorgu performansını optimize edin

İndeksler

İndeksler, Isar'ın sorgu optimizasyonundaki en güçlü özelliğidir. Tekil, bileşik ve çok girişli indeksleri etkin biçimde kullanmayı öğrenin.

İndeksleri anlamak, sorgu performansını optimize etmenin anahtarıdır!

İndeks Nedir?

İndeks olmadan sorgular her nesneyi tek tek taramak zorundadır. İndekslerle sorgular doğrudan ilgili verilere atlayabilir.

İndekssiz Örnek

@collection
class Product {
  Id? id;
  late String name;
  late int price;
}

İndekssiz Veri:

idnameprice
1Book15
2Table55
3Chair25
4Pencil3
5Lightbulb12
6Carpet60
7Pillow30
8Computer650
9Soap2

€30'dan büyük ürünleri bulmak için Isar 9 satırın tamamını kontrol eder:

final expensive = await isar.products.where()
  .priceGreaterThan(30)
  .findAll();

İndeksli

price alanına indeks ekleyin:

@collection
class Product {
  Id? id;
  late String name;
  
  @Index()
  late int price;
}

Oluşan İndeks (sıralı):

priceid
29
34
125
151
253
307
552
606
6508

Artık sorgu doğrudan ilgili satırlara atlar! ⚡

İndeks Oluşturma

Tek Alan İndeksi

@collection
class User {
  Id? id;

  @Index()
  late String email;

  @Index(type: IndexType.value)
  late String username;
}

Varsayılan - Değerin kendisini saklar. Tüm where cümlelerini destekler.

@Index(type: IndexType.value)
late String email;

// Destekler: equalTo, between, startsWith vb.
await isar.users.where()
  .emailStartsWith('john')
  .findAll();

Değerin hash'ini saklar. Yalnızca eşitlik kontrollerini destekler. Daha az yer kaplar.

@Index(type: IndexType.hash)
late String email;

// Yalnızca: equalTo
await isar.users.where()
  .emailEqualTo('john@example.com')
  .findAll();

Sadece List'ler için. Her elemanı ayrı ayrı hash'ler.

@Index(type: IndexType.hashElements)
late List<String> tags;

await isar.posts.where()
  .tagsElementEqualTo('flutter')
  .findAll();

Bileşik İndeksler

Karmaşık sorgular için birden fazla alanı birlikte indeksleyin:

@collection
class Person {
  Id? id;

  late String firstName;

  @Index(composite: ['firstName'])
  late String lastName;

  late int age;
}
// Bileşik indeksi verimli kullanır
final people = await isar.persons
  .where()
  .lastNameFirstNameEqualTo('Doe', 'John')
  .findAll();

Bileşik indeksler ilk alan tek başına kullanılarak da sorgulanabilir: .lastNameEqualTo('Doe')

Çok Alanlı Bileşik

@collection
@Index(composite: ['lastName', 'age'])
class Person {
  Id? id;
  late String firstName;
  late String lastName;
  late int age;
}
// Aşağıdakilerin hepsi bileşik indeksi kullanır:
.firstNameEqualTo('John')
.firstNameLastNameEqualTo('John', 'Doe')
.firstNameLastNameAgeEqualTo('John', 'Doe', 25)

Çok Girişli İndeksler

Liste elemanları için indeksler oluşturun:

@collection
class Post {
  Id? id;

  late String title;

  @Index(type: IndexType.value)
  late List<String> tags;
}
// Herhangi bir tag'e göre hızlı arama
final flutterPosts = await isar.posts
  .where()
  .tagsElementEqualTo('flutter')
  .findAll();

Çok girişli indeksler, çok elemanlı listelerde veritabanı boyutunu ciddi şekilde artırabilir.

Benzersiz İndeksler

Benzersizlik koşulları uygulayın:

@collection
class User {
  Id? id;

  @Index(unique: true)
  late String username;

  late int age;
}
await isar.writeAsync((isar) async {
  final user1 = User()
    ..id = 1
    ..username = 'john_doe'
    ..age = 25;
  await isar.users.put(user1); // ✅ eklendi

  final user2 = User()
    ..id = 2
    ..username = 'john_doe'
    ..age = 30;
  await isar.users.put(user2); // ✅ önceki kayıt sessizce silinir

  final son = await isar.users
      .where()
      .usernameEqualTo('john_doe')
      .findFirst();
  print(son);
  // {id: 2, username: john_doe, age: 30}
});

v4 benzersiz indeksler overwrite eder

Aynı anahtar kombinasyonunu ikinci kez yazarsanız Isar, önceki kaydı silip yenisini yazar. Duplicate girişleri reddetmek istiyorsanız kendiniz kontrol ekleyin:

await isar.writeAsync((isar) async {
  final varMi = await isar.users
      .where()
      .usernameEqualTo('john_doe')
      .findFirst();
  if (varMi != null) {
    throw StateError('username zaten kullanılıyor');
  }

  final user = User()
    ..id = 42
    ..username = 'john_doe'
    ..age = 30;

  await isar.users.put(user);
});

Büyük/Küçük Harf Duyarlılığı

String indekslerinde harf duyarlılığını kontrol edin:

@collection
class User {
  Id? id;

  @Index(caseSensitive: false)
  late String email;
}
// Her ikisi de aynı kullanıcıyı bulur
await isar.users.where().emailEqualTo('JOHN@example.com').findAll();
await isar.users.where().emailEqualTo('john@example.com').findAll();

Büyük/küçük harf duyarsız indeksler biraz daha fazla yer kaplar ama esnek sorgular sağlar.

Sıralama için İndeks

İndeksler süper hızlı sıralama sunar:

@collection
class Product {
  Id? id;

  late String name;

  @Index()
  late int price;
}
// ❌ Yavaş - tüm kayıtları yükleyip sonra sıralar
final cheapest = await isar.products
  .where()
  .sortByPrice()
  .limit(4)
  .findAll();
// ✅ Hızlı - sıralı indeksi kullanır
final cheapest = await isar.products
  .where()
  .anyPrice()
  .limit(4)
  .findAll();

İndeksli sıralama, sonuçların tamamını belleğe yükleyip sıralama ihtiyacını ortadan kaldırır!

Where Cümleleri

Maksimum performans için where cümlelerinde indeksleri kullanın:

@collection
class Product {
  Id? id;

  late String name;

  @Index()
  late int price;
}
// Hızlı - indeks kullanır
final products = await isar.products
  .where()
  .priceBetween(10, 100)
  .findAll();

// Hızlı - indeks + sıralama
final sorted = await isar.products
  .where()
  .anyPrice()
  .limit(10)
  .findAll();

// Hızlı - indeks + filtre
final filtered = await isar.products
  .where()
  .priceGreaterThan(50)
  .where()
  .nameStartsWith('iPhone')
  .findAll();

İndeks Tipi Karşılaştırması

TipBoyutWhere CümleleriKullanım Alanı
IndexType.valueBüyükHepsiTam metin arama, aralıklar
IndexType.hashKüçükSadece eşitlikBenzersiz kısıt, lookup
IndexType.hashElementsOrtaListe elemanlarıEtiket sistemleri, kategoriler

En İyi Uygulamalar

Doğru Alanları Seçin

Where cümlelerinde sık kullanılan alanları indeksleyin:

@collection
class User {
  Id? id;

  @Index() // Sık sorgulanır
  late String email;

  late String name; // Nadiren tek başına sorgulandığı için indeks yok
}

Aşırı İndeks Kullanmayın

Her indeks yazma süresini ve depolamayı artırır:

// ❌ Çok fazla indeks
@collection
class User {
  @Index() Id? id; // Id zaten indekslenmiş!
  @Index() late String email;
  @Index() late String name;
  @Index() late String phone;
  @Index() late int age;
}

// ✅ Sadece sorguladığını indeksle
@collection
class User {
  Id? id;
  @Index(unique: true) late String email;
  late String name;
  late String phone;
  late int age;
}

Bileşik İndeksleri Doğru Kullanın

// ✅ İyi - firstName + lastName birlikte sorgulanıyor
  @Index(composite: ['lastName'])
late String firstName;

// ❌ Kötü - ayrı ayrı sorgular
@Index()
late String firstName;
@Index()
late String lastName;

Sorgularınızı Profilleyin

Isar Inspector ile sorgu performansını analiz edin:

// Debug modunda inspector'ı etkinleştir
final isar = Isar.open(
  schemas: [UserSchema],
  inspector: true, // Inspector'ı aç
);

İndeks Sınırlamaları

  • String'lerin yalnızca ilk 1024 baytı indekslenir
  • Web'de bileşik indeksler en fazla 3 alan içerebilir
  • İndeksler yazma sürelerini artırır
  • Ek depolama alanı tüketir

Sonraki Adımlar

Son Güncelleme