Soru OrderBy (). Last () veya OrderByDescending (). İlk () performansı


Bunun muhtemelen bir mikro optimizasyon olduğunu biliyorum, ancak yine de kullanımda bir fark olup olmadığını merak ediyorum.

var lastObject = myList.OrderBy(item => item.Created).Last();

veya

var lastObject = myList.OrderByDescending(item => item.Created).First();

Linq'in nesneler ve Linq to Entities için yanıtları arıyorum.


28
2017-07-13 14:37


Menşei


Her birinden birkaç çalışma yaparak, her biri bir milyonun üzerinde (birkaç milyon?) Yineleme yapın. Cevabını alacaksın. - Oded
+1: İyi Soru: Şahsen ben onu kullanırdım. SQL'de en azından bu, ilk değer bulunduğunda işlemin tamamlanmasına neden olur. Listenin sonunu bulmak için önceki seçeneğin listeyi tamamen sipariş etmesi gerekir. Bunun Linq'e nasıl uygulanacağından emin değilsiniz. - Jon Egerton
@Jon - Linq uygulamasına ve sorguyu temel veri deposuna (varsa) nasıl çevirdiğine bağlıdır. - Oded
EF desteklemeyecek Last()eğer doğru hatırlarsam. Herhangi bir oranda, Linq-to-Objects'taki fark, İlk / Son aramalar olacaktır. Sipariş meli her iki şekilde de aynı maliyete ve meli en pahalı işlem olmak. First() sonuçta yalnızca ilk öğeye yineleme gerekir, oysa Last() Sonuç dizisinin tamamını değiştirir, ancak büyüktür. - Anthony Pegram
Hakkında ilginç bir bit Last() o döküm etmeye çalışır IEnumerable<T> için IList<T> ve dönüş list[count - 1]. Eğer değilse IList<T>Daha sonra, son öğeyi döndürmek için koleksiyonun tamamını numaralandırır. - Joel B Fant


Cevaplar:


Her iki sıralama yönteminin de eşit zaman aldığını varsayalım (ve bu büyük bir 'if'), o zaman ilk yöntemin .Last()Potansiyel olarak tam sayım gerektiren.

Ve bu argüman muhtemelen bir SQL yönelimli LINQ için daha güçlü tutar.


14
2017-07-13 14:45



Beklemek isterim Last() Her iki durumda da sabit bir zaman erişimi olması. SQL için TOP 1 sonra ORDER BY ... DESC. Bir dizi için sadece list[list.Length - 1]. Senin düşüncelerin? - Yuck
@Yuck, listeyi değiştirmeyen diziyi sipariş ediyorsunuz. list[lastIndex]  değil En yüksek veya en düşük sipariş edilen ürünü al. Sonra OrderBy, First() veya Last() Artık doğrudan listeye karşı çalışmıyor, IEnumerable dizisi (kesinlikle nesneler arası terimlerle konuşulur). - Anthony Pegram
@Yuck: Anthony doğru. Last() bir oyuncuyu denemek IList<T> önce son endeksi kullanabilmek için, ancak aksi takdirde numaralandırılacaktır. Sizin select top 1 ... order by desc ile aynı olmaz list[count-1]. Birinde azalan sıralı bir diziden ilkini alıyorsunuz, diğerinde ise artan sıralı bir dizinin sonunu alıyorsunuz Eğer içine indeksleyebilirsiniz. SQL örneğiniz ile aynı olurdu OrderByDescending().First(), değil OrderBy().Last(). - Joel B Fant


(cevabım Linq'den Objects'e, Varlıklara Linq değil)

İki talimat arasında büyük bir fark olduğunu sanmıyorum, bu açıkça bir mikro optimizasyon olgusudur. Her iki durumda da, koleksiyonun genellikle karmaşıklığı anlamına gelen, sıralanması gerekir. O(n log n). Ancak aynı sonucu kolayca karmaşık bir şekilde elde edebilirsiniz. O(n)Min ve maksimum değerlerin toplanması ve izlenmesi ile numaralandırılır. Jon Skeet onun içinde bir uygulama sunuyor MoreLinq proje şeklinde MaxBy uzatma yöntemi:

var lastObject = myList.MaxBy(item => item.Created);

5
2017-07-13 14:53





Her iki durumda da, temel koleksiyonlarınıza biraz bağlıdır. Koleksiyonların siparişten önce nasıl göründüğüne dair ön bilgiye sahipseniz ve birini seçerseniz, birini seçebilirsiniz. Örneğin, listeyi biliyorsanız genellikle artan (veya çoğunlukla artan) sıralı bir sıralamada ilk tercihi tercih edebilirsiniz. Ya da, artan sıralanan SQL tablolarında dizinleriniz olduğunu biliyorsanız. SQL optimizer muhtemelen bununla başa çıkabilir.

Genel bir durumda eşdeğer ifadelerdir. Mikro optimizasyon dediğin zaman haklıydın.


3
2017-07-13 14:42





Üzgünüm, bu doğrudan sorunuzu cevaplamıyor, ama ...

Neden daha iyi bir optimizasyon yapmıyoruz ve Jon Skeet'in MaxBy veya MinBy?

Bu, sunduğunuz her iki alternatifte O (n log n) 'nin aksine O (n) olacaktır.


3
2017-07-13 14:49





OrderBy ve OrderByDescending öğelerinin aynı performansı ortalama aldığını varsayarak, ilk öğeyi almak, öğe sayısı büyük olduğunda sonuncusundan daha iyi olur.


1
2017-07-13 14:44



Cevabınız benzer olduğundan, Henk Holterman'a yaptığım yorumu görün. Operasyonların aynı olmasını beklerim. - Yuck


sadece iki sent: beri OrderBy veya OrderByDescending Zaten tüm nesnelerin üzerinde yinelemek zorunda, hiçbir fark olmamalıdır. Ancak, eğer ben olsaydım muhtemelen sadece tüm foreach En yüksek karşılaştırma maddesini tutmak için bir karşılaştırmayla, hangi sıralama büyüklüğü sırasına göre değil, O (n) araması olacaktır.


1
2017-07-13 14:45



Bunun neden oy kullanmadığından, maksimum / dakikaya işlevsel olarak eşdeğer ve anlaşılması daha kolay olduğundan emin değil. - B2K