Bir sonraki ve önceki element için sorgular optimize

oy
28

Ben tam sorgu akmayan bir kaydın sonraki ve önceki kayıtları almak için en iyi yol arıyorum. Ben yerinde tam uygulanan bir çözüm var ve orada bunu yapmak için daha iyi bir yaklaşım olup olmadığını bilmek istiyorum.

en bir hayali manav için bir web sitesi inşa ediyoruz diyelim. Onun HTML sayfaları yanı sıra, her hafta onun sitesinde özel teklifler bir listesini yayınlamak istiyor. O gerçek bir veritabanı tablosu ikamet için bu teklifi istiyor ve kullanıcıları üç şekilde teklifler sıralamak mümkün olmalıdır.

Her öğesi de teklif daha metinsel bilgiler ve önceki ve sonraki düğmeleri ile bir ayrıntı sayfası olması gerekiyor. Önceki ve sonraki düğmeleri komşu girişler yönlendirmesi gereken sıralama kullanıcı listesi için seçmişti bağlı .

alt metni http://www.pekkagaiser.com/stuff/Sort.gif?

Açıkçası, için sonraki düğmesi Domates, Sınıf I İlk örnekte, içinde Elmalar, sınıf 1 olmak zorundadır Armutlar, sınıf I üçüncü ikinci ve hiçbirinde.

Ayrıntı görünümünde görevdir bir sorgu her zaman çalıştırmadan sonraki ve önceki öğeleri belirlemek için kullanılabilir bilgi olarak listenin sıralama düzeninde ile, (en biz GET parametresi üzerinden olsun diyelim ?sort=offeroftheweek_priceve güvenlik sonuçlarını göz ardı) .

Açıkçası, sadece bir parametre olarak bir sonraki ve önceki elemanların kimliğini doğru akla gelen ilk çözümdür. Sonuçta, biz zaten bu noktada kimlikleri biliyorum. Ama, bu burada bir seçenek değildir - bu benim gerçek dünya kullanım durumları çoğunda bu basitleştirilmiş örnekte çalışır, ancak olmazdı.

Benim CMS Benim şu anki yaklaşımı ben önbellek sıralama adlı bir şeyi kullanıyor. Bir liste yüklendiğinde, ben adlı bir tablodaki kayıtları öğe pozisyonlarını saklamak sortingcache.

name (VARCHAR)             items (TEXT)

offeroftheweek_unsorted    Lettuce; Tomatoes; Apples I; Apples II; Pears
offeroftheweek_price       Tomatoes;Pears;Apples I; Apples II; Lettuce
offeroftheweek_class_asc   Apples II;Lettuce;Apples;Pears;Tomatoes

Açıkçası, itemskolon gerçekten Sayısal kimliklerin doldurulur.

Detay sayfasında, şimdi uygun erişmek sortingcachegetirme, kayıt items, o patlayacak, sütun geçerli öğe kimliği aramak ve önceki ve sonraki komşusu dönün.

array(current   => Tomatoes,
      next      => Pears,
      previous  => null
      );

Bu, listeleri oluşturmak için sorgu her detay görünümünde çalışan dışındaysa, (öyle) çok pahalı sadece kayıtların sınırlı sayıda çalışan ve gereksiz verileri oluşturur, ama gerçek dünyada varsayalım, besbelli pahalı soru ve bazı önbelleğe alma gereklidir.

Sorularım:

  • Bu sorgu emir değişen komşu kayıtları bulmak için iyi bir uygulama olduğunu düşünüyor musunuz?

  • Eğer performans ve basitlik açısından daha iyi uygulamaları biliyor musunuz? Bunun tamamen eskimiş kılan şey mi biliyorsun?

  • Programlama Teoride, bu sorun için bir isim var mı?

  • adı Sıralama önbellek Bu teknik için uygun ve anlaşılabilir mi?

  • Bu sorunu çözmek için herhangi bir tanınmış ortak düzen var? Onları nasıl çağırıyorlar?

Not: Benim sorum listesi oluşturuyor, ya da ne kadar ayrıntı görünümünü görüntülemek için ilgili değildir. Bunlar sadece örnektir. Benim sorum temel işlevi yeniden sorgu imkansız olduğunda kaydın komşularını belirleme ve oraya en hızlı ve ucuz yolu.

Net olmayan bir şey varsa, bir yorum bırakın ve ben netleştirecek ediniz.

Bir ödül başlayarak - belki orada bu konuda biraz daha bilgi orada bir yerde.

Oluştur 22/02/2010 saat 12:06
kaynak kullanıcı
Diğer dillerde...                            


11 cevaplar

oy
-3

Yani iki görevi vardır:

  1. öğelerin sıralı liste oluşturmak (BY farklı SİPARİŞ seçer)
  2. Her bir öğe ile ilgili ayrıntıları (mümkünse önbelleğe sahip veritabanından ayrıntıları SEÇ) göstermektedir.

Sorun nedir?

Not: sipariş listesi çok büyük olabilir eğer sadece PAGER işlevselliği uygulamaya gerek. örneğin sorgu içine "SINIRLAMASINI 5" ekleyip "göster önümüzdeki 5" düğmesine sağlamak isteyebilirsiniz, farklı uygulamalar söz konusu olabilir. Bu düğmeye basıldığında, gibi durum "fiyat <0,89 SINIR 5 NEREDE" eklenir.

Cevap 22/02/2010 saat 15:04
kaynak kullanıcı

oy
16

İşte bir fikirdir. Bakkal ekler / son kullanıcı görüntülemek için veri seçtiğinde yerine yeni teklifler günceller zaman bir güncelleme pahalı operasyonlar boşaltma başladı. Bu tür veriyi işlemek için bir dinamik olmayan bir yol gibi görünebilir, ancak bu hızını arttırabilir. Ve bildiğimiz gibi, her zaman performans ve diğer kodlama faktörlere arasında bir ters orantı vardır.

Her teklif ve her çeşit seçeneği için sonraki ve önceki tutmak için bir tablo oluşturun. (Her zaman üç çeşit seçenekleri olacak eğer Alternatif olarak, teklif tabloda bu depolayabilir - Sorgu hız veritabanınızı denormalize iyi bir neden)

Yani bu sütunları olurdu:

  • Sıralama Türü (Unsorted, Fiyat, Sınıf ve Fiyat Azalan)
  • Teklif kimliği
  • Önceki kimliği
  • Sonraki İD

Teklif ayrıntıları sayfası için detay bilgi veritabanından sorgulandığında, NextID ve PrevID sonuçlarının bir parçası olacaktır. Yani sadece her detay sayfası için bir sorgu gerekir.

Bir teklif eklenmiştir güncellenmiş veya her silindiğinde, sen sorttype tablonun bütünlüğü / doğruluğu doğrulayan bir işlemi çalıştırmak gerekir.

Cevap 22/02/2010 saat 20:20
kaynak kullanıcı

oy
1

Ben doğru anladım emin değilim, bu yüzden eğer, sadece söyle;)

Yani biz var, en givens sıralı listesi ve bu listede ofset akım için sorgu olduklarını, diyelim $queryve bir $n.

sorguları en aza indirmek için çok bariz bir çözüm, bir kerede tüm veri getirmek için olacaktır:

list($prev, $current, $next) = DB::q($query . ' LIMIT ?i, 3', $n - 1)->fetchAll(PDO::FETCH_NUM);

Bu açıklama, önceki, şimdiki ve cari sıralama sırayla veritabanından sonraki unsurları getirir ve ilgili değişkenlere ilişkili bilgileri koyar.

Bu çözüm çok basit Ama, bir şey yanlış varsayalım.

Cevap 07/02/2011 saat 20:31
kaynak kullanıcı

oy
2

Ben de bu biriyle kabus gördüm. Geçerli yaklaşım bile 10k öğesi listeleri için en iyi çözüm gibi görünüyor. Http oturumunda liste görünümünün kimlikleri önbelleğe ve sonra görüntülemek için bu kullanarak önceki / sonraki (şimdiki kullanıcı için kişiselleştirilmiş). Bu filtre ve bunun yerine sadece 3'ün öğelerin başlangıç listesini sıralamak için çok çeşitli yolları vardır, özellikle iyi çalışır
bir görüntülenmesini sağlamanın bütün kimlikleri listesi depolayarak, Ayrıca "you are at X out of Y"kullanışlılık arttırıcı metni.
JIRA sonraki / önceki

Bu arada, bu nedir JIRA yanı yok.

doğrudan sorulara cevap için:

  • Filtre / sıralama ve öğe türleri daha karmaşık karga zaman herhangi bir ek kod karmaşıklık olmadan ölçekler çünkü Evet iyi bir uygulamadır. Ben "sonsuz" filtre / sıralama varyasyonları ile 250k makale ile bir üretim sisteminde kullanıyorum. kullanıcı büyük ihtimalle prev tıklayabilir asla veya 500'den fazla kez Sonraki (O büyük olasılıkla geri dönüp arama rafine veya paginate edeceğiz) beri 1000 önbelleklenebilir kimlikleri Kırpma da bir ihtimaldir.
  • Ben daha iyi bir yol bilmiyorum. Ama sınırlı ve bu (hiçbir http oturumuna ile) kamu site oldu sıralar sonra ben büyük olasılıkla denormalize olsaydın.
  • Dunno.
  • Evet, sıralama önbellek iyi geliyor. Projemde "Navigasyon arama sonuçlarında" "/ önceki arama sonuçlarında sonraki" veya diyoruz.
  • Dunno.
Cevap 07/02/2011 saat 21:04
kaynak kullanıcı

oy
2

Genel olarak, dizinler veri denormalize. Aynı sıralar halinde depolanabilir, ama neredeyse her zaman daha sonra veri için ayrı bir yolculuk yapmak, benim sonuç kimlikleri almak. Bu çok basit verileri önbelleğe yapar. gecikme düşüktür ve bant genişliği yüksek, ancak böyle sitenin çok JavaScript koyulabileceği bir AJAX web sitesi olarak, yüksek bir gecikme, düşük bant genişliği uygulaması varken böyle bir strateji çok yararlıdır nerede PHP'de çok önemli değildir.

Hep sonuçların listelerini önbelleğe ve ayrı ayrı sonuçlar kendileri. şey bir liste sorgunun sonuçlarını etkiliyorsa, liste sonuçlarının önbellek yenilenir. şey sonuçlar kendilerini etkiliyorsa, özellikle bu sonuçlar yenilenir. Bu bana etkili önbelleğe alma ile sonuçlanır şeyi yenilemeye gerek kalmadan ikisinden birini güncellemek için izin verir.

Sonuçların benim listeleri nadiren değiştirmek beri, aynı anda tüm listeleri oluşturabilir. Bu ilk tepkisi biraz daha yavaş yapabilir, ama (bütün listeleri tek önbellek girdisi depolanır) önbellek yenilenmesi kolaylaştırır.

Ben tüm liste önbelleğe sahip olduğundan, veritabanı yeniden ziyaret etmeden komşu öğeleri bulmak için Önemsiz. şansla, bu öğeler için veriler de önbelleğe edilecektir. JavaScript veriler sıralanırken Bu özellikle kullanışlıdır. Zaten istemci üzerinde önbelleğe bir kopyası varsa, ben anında çare olabilir.

Sorularınızı özel olarak cevaplamak için:

  • Evet, vaktinden komşular öğrenmek için harika bir fikir, ya da her türlü bilgi istemci maliyeti artık düşük ve yeniden hesaplamak için maliyeti yüksektir, özellikle de sonraki erişmek olasıdır. Sonra sadece ekstra öncesi hesaplanması ve hıza karşı depolama kapalı bir ticaret.
  • performans ve basitlik açısından, mantıksal olarak farklı şeylerdir birlikte ipe şeyler kaçının. Endeksler ve veri, farklı farklı zamanlarda değiştirilmesi olasıdır (endeksler etkileyecek yeni bir veri ekleyerek mesela ama mevcut veri) ve dolayısıyla ayrı ayrı erişilebilir olmalıdır. Bu, tek iş parçacıklı açısından biraz daha az verimli olabilir, ancak birlikte bir şeyler kravat her sefer, etkinlik ve asychronosity (ölçekleme anahtarı asychronosity olan) önbelleğe kaybetmek.
  • vaktinden verileri almak için kullanılan terim önokuma olduğunu. Önokuma erişim veya arka planda bir zamanda olabilir, ancak önceden getirilen veriler gerçekte ihtiyaç oluşmadan önce. Aynı şekilde ön hesaplama ile. Bu gerektiğinde almak için şimdi maliyetinin ticaret-off, depolama maliyeti yoktur ve bedel.
  • "Sıralama önbellek" bir apt adıdır.
  • Bilmiyorum.

Eğer şeyleri önbelleğe Ayrıca, mümkün olan en jenerik düzeyde bunları önbelleğe. Bazı şeyler böyle bir kataloga göz olarak diğerleri kullanıcı agnostik olabilir, (örneğin, bir arama sorgusu için sonuçları gibi) kullanıcının belirli olabilir. Hem önbelleğe yararlanabilir. katalog sorgusu sık ve biraz her zaman kazanmak ve arama sorgusu pahalı olabilir ve bir sürü birkaç kez kurtarabilir olabilir.

Cevap 09/02/2011 saat 08:00
kaynak kullanıcı

oy
0

cilt meşhur kedi olarak bunu yapmak için birçok yol vardır. Yani burada benim bir çift.

Orijinal sorgu kaç olduğunu söylemek hangi pahalı ise o zaman da pahalı sonuçları ile bu doldurma muhtemelen bir bellek tablo başka bir tablo oluşturmak ve nadiren ana sorguyu çalıştırın.

Bu ikinci tablo daha sonra her görünümde sorgulanabilir olabilir ve sıralama uygun sıralama düzeni ayarlama kadar basittir.

gerekli olmadığından bu şekilde yeni veri tutmak, fakat pahalı terimi kullanımının en aza indirilmesi, ilk tablodan sonuçları ile ikinci bir tablo yeniden doldurmak.

Alternatif olarak, o zaman bir php dizide tüm verileri depolamak ve memcached kullanarak saklayın olabilir db'ye bağlanırken bile kaçınmak istiyorsanız. Bu çok hızlı olması ve listeleri verimli kaynak olacağını çok büyük değildi sağlanan olacaktır. ve kolayca sıralanabilir.

DC

Cevap 11/02/2011 saat 05:19
kaynak kullanıcı

oy
0

Temel varsayımlar:

  • Özel haftalıktır
  • Biz site seyrek ... muhtemelen günlük değiştirmek bekleyebilirsiniz?
  • Biz eter bir API ile veritabanına güncellemelerini kontrol etmek veya tetikleyicileriyle yanıt verebilir

Site günlük bazda değiştirirse, tüm sayfaları statik gecede oluşturulan düşündürmektedir. aracılığıyla her tür dereceden yinelenir Bir sorgu ve ilgili tüm sayfaları yapar. Dinamik öğeler olsa bile, oran statik sayfa öğeleri dahil ederek onlara hitap edebilir yönünde. Bu optimum sayfa hizmeti ve hiçbir veritabanı yükünü sağlayacak. Aslında, muhtemelen ayrı sayfalara ve sayfalara dahildir önceki / sonraki unsurları yaratabilir. Bu sıralamak için 200 yolları deli olabilir, ama 3 ile bundan büyük bir hayranıyım.

?sort=price
include(/sorts/$sort/tomatoes_class_1)
/*tomatoes_class_1 is probably a numeric id; sanitize your sort key... use numerics?*/

nedense bu mümkün değilse, ben ezberlenmesi muhtaç olman. Memcache şey bu tür için popüler (cinas!). şey veritabanına itildiğinde, sen doğru değerlerle önbelleği güncellemek için bir tetikleyici verebilir. uygun yeniden bağlamak (this.next.prev = this.prev, vs.) - güncellenmiş madde 3 bağlantılı listelerde varmış gibi sen olsaydın aynı şekilde yapın. Bu itibaren, sürece önbellek fazla doldurmayın sürece, birincil anahtar moda bellekten basit değerleri çekerek olacak.

Bu yöntem seçme ve güncelleme / insert yöntemleri hakkında bazı ekstra kodlama alacak, ama oldukça alt düzeyde olmalıdır. Sonunda, en fazla bakacağız [id of tomatoes class 1].price.next. O anahtar önbelleğinizde ise, altın. Değilse, önbellek ve ekrana içine yerleştirin.

  • Bu sorgu emir değişen komşu kayıtları bulmak için iyi bir uygulama olduğunu düşünüyor musunuz? Evet. Beklenen yaklaşan istekleri göz-aheads gerçekleştirmek için akıllıca olacaktır.
  • Eğer performans ve basitlik açısından daha iyi uygulamaları biliyor musunuz? Bunun tamamen eskimiş kılan şey mi biliyorsun? Umarım yukarıda
  • Programlama Teoride, bu sorun için bir isim var mı? Optimizasyon?
  • Adı "Sıralama önbellek" Bu teknik için uygun ve anlaşılabilir mi? Belirli uygun adından emin değilim. O sıralar bir önbelleğidir, önbelleğe alma, ama anlık bir anlayış iletmek bir "sıralama önbelleği" var bana emin değilim.
  • Bu sorunu çözmek için herhangi bir tanınmış ortak düzen var? Onları nasıl çağırıyorlar? Caching?

Maalesef benim atık cevaplar tür işe yaramaz, ama benim anlatı çözümleri oldukça yararlı olması gerektiğini düşünüyorum.

Cevap 11/02/2011 saat 18:13
kaynak kullanıcı

oy
0

Sen kurtarabilecek satır numaralarını içine sipariş listelerinin görünümleri ve siz (current_rownum-1) ve (current_rownum + 1) satır numaraları altındaki listede, önceki ve sonraki öğeleri ulaşabilir.

Cevap 12/02/2011 saat 14:01
kaynak kullanıcı

oy
0

Sorun / datastructur çift yönlü grafik olarak adlandırılır veya birkaç bağlı listeler var diyebiliriz.

Bağlı bir listenin olarak düşünmek, sadece her sıralama ve önceki / sonraki anahtar için ürün tabloya alanları ekleyebilir. Ama DB Kişi GOTO gibi, bunun için seni öldürecek.

Eğer bir (bi) yönlü grafiğin olarak düşünmek ise, Jessica'nın cevabı ile gitmek. asıl sorun sipariş güncellemeler pahalı operasyonlar olduğunu vardır.

 Item Next Prev
   A   B     -
   B   C     A
   C   D     B
   ...

Yeni sırayla A, C, B, D, bir ürün konumunu değiştirirseniz, 4 satır güncellemek zorunda kalacaktır.

Cevap 13/02/2011 saat 02:20
kaynak kullanıcı

oy
4

Ben Jessica biraz benzer bir fikrim var. Ancak, bunun yerine bir sonraki ve önceki sıralama öğelere bağlantılar depolanması, her çeşit türü için sıralama düzeni saklayın. önceki veya sonraki rekor bulmak için, önce SortX = currentSort ++ veya SortX = currentSort-- bulunduğu satırı olsun.

Örnek:

Type     Class Price Sort1  Sort2 Sort3
Lettuce  2     0.89  0      4     0
Tomatoes 1     1.50  1      0     4
Apples   1     1.10  2      2     2
Apples   2     0.95  3      3     1
Pears    1     1.25  4      1     3

Bu çözüm çok kısa sorgu sürelerini doğuracak ve Jessica'nın fikri daha az disk alanı alacaktı. Anladığını eminim sen yeniden hesaplanması ve tüm sıralama düzenleri saklamak zorunda olduğundan Ancak, veri satırına güncellenmesi maliyeti özellikle yüksektir. veri güncellemeleri nadirdir ve her zaman toplu olarak gerçekleşmesi, özellikle o zaman bu çözüm iyi olabilir ama eğer hala, durumunuza bağlı.

yani

once_per_day
  add/delete/update all records
  recalculate sort orders

Bu yararlı olduğunu umuyoruz.

Cevap 13/02/2011 saat 03:30
kaynak kullanıcı

oy
0

Özür Ben yanlış anlamış, ama kullanıcı sunucuya erişen arasında sıralı liste korumak istiyorsanız düşünüyorsanız. Eğer öyleyse, cevap sıra önbelleğe alma stratejisi ve teknolojiler konusunda ziyade veritabanı sorgu / şema optimizasyonu yatıyor olabilir.

Benim yaklaşımım, ilk alınan bir kez) (dizi seri ve sonra ayrı bir depolama alanına bu önbelleğe olacaktır; Bu bireysel olarak oturum verilerine yoluyla her kullanıcı için / APC / sabit disk / mongodb / vs ve muhafaza onun önbellek yer ayrıntılarını memcached gerçekleştirdiklerini öğrenebilirsiniz. Gerçek depolama arka uç doğal olarak ilgili fazla detaya girmiyoruz dizinin, büyüklüğüne bağlıdır, ancak birden fazla sunucu üzerinde memcached ölçekler, büyük ve biraz daha büyük gecikme pahasına daha da Mongo olacaktır.

Ayrıca, gerçek dünyada kaç çeşit permütasyon göstermez; örneğin kullanıcı başına ayrı listeleri önbelleğe gerekiyor, yoksa küresel ardından sıralama permütasyon başına önbellek ve PHP üzerinden ihtiyacım yok filtreleyebilirsiniz ?. Verdiğiniz örnekte, sadece iki ben oturum verilerinin () unserialize için gerekli hem permütasyon ve mağaza önbelleğe istiyorum.

Kullanıcı siteye döndüğünde, önbelleğe alınan verilerin değerini Canlı ve hala geçerli eğer yeniden kullanmak için Zaman kontrol edin. Ayrıca / / GÜNCELLEME IGNORE INSERT üzerinde çalışan bir tetikleyici sahip basitçe ayrı bir tabloda bir zaman damgası alanı oluşturuyor özel teklifler için SİL ediyorum. Bu hemen önbellek bayat ve sorgu çok düşük sorgu maliyeti için yeniden çalıştırmak olması gerekiyordu belirtmek istiyorum. yalnızca tek bir alan ayarlamak için tetiği kullanımı hakkında çok şey o masayı dışarı eski / gereksiz değerleri budama konusunda endişelenmenize gerek yok olmasıdır.

Bu ancak değiştirilmiş hangi sıklıkta, iade edilen verilerin boyutu bağımlı olur uygundur ve ne önbelleğe alma teknolojileri sunucu üzerinde mevcut olup olmadığı.

Cevap 13/02/2011 saat 15:47
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more