Sayfalandırma ve Varlık Çerçevesi

0

Soru

Mobil uygulamamda, SQL Server veritabanımın bir tablosundan veri almaya çalışıyorum. EF kullanıyorum ve daha iyi performans için sayfalandırmayı kullanmaya çalışıyorum. Tablonun son öğesinden veri almam gerekiyor. tabloda 20 satır varsa, sayfa 0, kimlikler 20, 19, 18, 17, 16 için sayfa 1 kimlikleri 15, 14, 13, 12, 11 vb.İçin ihtiyacım var...

Sorun şudur: "A" kullanıcısı tablodan veri indirirken, "B" kullanıcısı satır ekliyorsa ne olur? "A" kullanıcısı Sayfa 0 alırsa (yani kimlikler 20, 19, 18, 17, 16), ve aynı anda "B" kullanıcısı satır ekler (böylece ID 21), klasik sorgu ile sayfa 1 için "A" kullanıcısı kimlikleri alır 16, 15, 14, 13, 12... yani başka bir zaman kimliği 16

Kodum çok basit:

int RecordsForPagination = 5; 
var list = _context.NameTable
                   .Where(my_condition)
                   .OrderByDescending(my_condition_for ordering)
                   .Skip (RecordsForPagination * Page)
                   .Take (RecordsForPagination)
                   .ToList();

Elbette Page ön uçtan gelen int'dir.

Sorunu nasıl çözebilirim?

Bir çözüm buldum ama mükemmel olup olmadığını bilmiyorum. Kullanabilirim

.SkipWhile(x => x.ID >= LastID) 

yerine

.Skip (RecordsForPagination * Page)

ve tabii ki LastID her zaman ön uçtan gönderilir.

Bu kodla performansın her zaman iyi olduğunu düşünüyor musunuz? Daha iyi bir çözüm var mı?

entity-framework linq sql-server
2021-11-22 23:06:34
1

En iyi cevabı

1

Performans etkileri büyük ölçüde SQL Dizin uygulamanıza ve order by yan tümcesine bağlı olacaktır. Ancak beklenen sonuçları almakla ilgili olduğu kadar performansla ilgili de bir soru değil.

Yığın Taşması, herhangi bir sayfanın sonuna geldiğinizde, bir sonraki sayfanın, temel kayıt kümesi değiştiğinden (daha fazla gönderi eklendiğinden) görüntülediğiniz sayfadan kayıtlar içerebileceği bir etkinlik hacminin olduğu harika bir örnektir.

Bunu gündeme getiriyorum çünkü canlı bir sistemde genel olarak kabul edilir ve bazı durumlarda beklenen bir davranıştır. Geliştiriciler olarak, tek bir sonuç kümesini sürdürmeye çalışmanın ek genel giderlerini takdir ediyoruz ve sayfaları yinelerken çoğaltmalara benzeyen şeyleri engellemeye çalışırken genellikle çok daha düşük bir değer olduğunu kabul ediyoruz.

Kullanıcılara bunun neden olduğunu açıklamak genellikle yeterlidir, çoğu durumda bunu kabul ederler

Özgün sonuç kümesindeki yeri korumanız sizin için önemliyse, sorguyu a ile sınırlamanız gerekir. Where yan tümcesi, ancak özgün sorgudaki kimliği veya zaman damgasını almanız gerekir. Sizin durumunuzda kullanmaya çalışıyorsunuz LastID ancak, son kimliği almak için kendi başına ayrı bir sorgu gerekir, çünkü orderby yan tümcesi onu etkileyecektir.

Gerçekten kullanamazsın. .SkipWhile(x => x.ID >= LastID) bunun için, skip, sıralamadan etkilenen ve ifadenin değerlendirdiği ilk örneği devre dışı bırakan sıralı bir işlem olduğundan false, yani sipariş dayalı değilse Id, atlama süreniz hiç kayıt atlamamanıza neden olabilir.

int RecordsForPagination = 5; 
int? MaxId = null;
...
var query = _context.NameTable.Where(my_condition);
// We need the Id to constraint the original search
if (!MaxId.HasValue)
    MaxId = query.Max(x => x.ID);

var list = query.Where(x => x.ID <= MaxId)
                .OrderByDescending(my_condition_for ordering)
                .Skip(RecordsForPagination * Page)
                .Take(RecordsForPagination);
                .ToList();

Bu, istemciden dB'ye gidiş dönüş olmadan bilindiği için zaman içinde bir noktaya göre filtrelemek genellikle daha basittir, ancak uygulamaya bağlı olarak tarihlerdeki filtreleme daha az verimli olabilir.

2021-11-22 23:55:04

Amacım Lastıd'yi dB'den almak değildi (çünkü dediğiniz gibi, bu Db'nin kendisinden etkilenecektir). niyetim şuydu: - Ön uç Sayfa 0'ı alır ve sonuç kimliklerdir 20, 19, 18, 17, 16 - Ön uç Sayfa 1'i alır ve arka uç iki param'a geçer: Sayfa 1 ve önceki Sayfanın lastıd'si (bu durumda LastID = 16) - > sonuç kimlikler olacaktır 15, 14, 13, 12, 11... ve böyle devam eder. ingilizcem mükemmel değil... aynı şeyi mi söylüyoruz?
user1106897

@ user1106897 Chris'in başvurduğu tekniğe Anahtar Kümesi Sayfalandırma denir ve genellikle satırlara göre sayfalamaktan çok daha iyidir, bu da bahsettiğiniz şeydir
Charlieface

Bunun çok fazla olduğunu da bir soru performans: disk belleği satır ise son derece verimsiz olarak önceki tüm satırları ihtiyacımız olacak okumak her zaman. Destekleyici bir dizin varsa, anahtara göre (veya bu durumda zamana göre) sayfalama oldukça verimlidir
Charlieface

Charlie face bağlantı için çok teşekkür ederim, gerçekten takdir. Tavsiyeleri kullanmaya çalışacağım
user1106897

Teşekkürler @ Charlieface performans açıklamasının daha çok "performansı unutun, siparişi değiştirirseniz(kimliğe göre) sorunu çözmeyecek" olması gerekiyordu. Harika bağlantı da!
Chris Schaller

Diğer dillerde

Bu sayfa diğer dillerde

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................