Veritabanı endeksleri eklemek için erken optimizasyon var mı?


61

Bugün bir meslektaşım başvurumuzdaki tüm soruları gözden geçirmemizi ve buna göre endeksleri eklememizi önerdi.

Bunun erken optimizasyon olduğunu düşünüyorum çünkü uygulamamız henüz yayınlanmadı. Canlı yayına girdikten sonra yavaş sorguları izlemeyi ve ardından buna göre indeksler eklemeyi önerdim.

Veritabanınızı tasarlarken genel fikir birliği nedir, her yeni bir sorgu yazışınızda eşleşen bir dizin eklemeniz gerekir mi? Yoksa sadece nasıl gittiğini görmek ve görmek daha mı iyi?


32
Bu bir fikir meselesi olabilir, ancak bazı endekslerin önceden eklenebileceğini düşünüyorum.
Basile Starynkevitch

2
@BasileStarynkevitch Tamamen birincil anahtar dizinlerimize ve eserlere sahip olduğumuza tamamen katılıyorum. Ama çizgiyi nerede çiziyorsun?
Marco de Jongh

1
Deneyimden iki kuruş: İlk arama sorgularımın bir kısmını veritabanımızın bir alt kümesinde test ediyordum. Yaptığım testler yerel kopyamda gayet iyi. Daha sonra uygulamayı tam veritabanını barındıran hazırlama alanına itdim. Testlerim <500 msn'de çalıştı , oysa evreleme sistemi çözmek birkaç dakika sürdü . Patronum, uygulamanın neden yüklenmediği konusunda iyice kafam karıştı. Açıklayın -tipi işlemleri arkadaşınızdır ... En azından büyük masalarda sıralı taramaları arayın, en azından!
Chris Cirefice

2
Dizin eklememek bubblesort kullanmak gibidir. Çoğu zaman test ederken hiçbir problem bulamazsınız ancak programınız yayına girmeye başladığında bir çok problemle karşılaşırsınız. Ve indeksler kolayca hız farkında 100 faktör yapabilir.
Pieter B,

3
Sadece daima hatırlayın: Dizin, sorgularınızı hızlandıracak sihirli bir şey değildir. Bir Dizin çoğu DML İşleminde maliyet yaratacaktır ve türe bağlı olarak birçok kişi aynı tabloyu güncellediğinde çok fazla beklemeye yol açabilir. Sorgular için: Bir FTS'nin en hızlı olduğu ya da Bölümlemenin sizin için tüm işleri yaptığı bir dizinden hiç faydalanmayan birçok sorgu vardır. - Sadece yararlı olacağını bildiğiniz bir dizin ekleyin!
Falco

Yanıtlar:


132

Erken optimizasyon, belirsiz, sezgisel bir anlamdan dolayı bir şeyi "optimize ediyor". Biliyorsunuz, muhtemelen kod okunabilirliği ve bakımının zararına bağlı olarak bu muhtemelen yavaş olacak . Performansla ilgili iyi bilinen iyi uygulamaları takip etmeyeceğimi kasten kastetmiyor.

Bazen bu çizilmesi zor bir çizgidir, ancak kesinlikle canlı yayına girmeden önce herhangi bir endeks eklememenin çok geç bir optimizasyon olduğunu söyleyebilirim ; Bu, en istekli ve en önemli kullanıcılarınız olan erken evlatçıları cezalandırır ve onlara, daha sonra incelemelerde, tartışmalarda vb. yayılacakları olumsuz bir görünüm verir. Dizin oluşturması gereken acı noktalarını bulmak için sorguları izlemek, iyi bir fikir, ancak bunu en geç beta sürümden yapacağımdan emin olabilirim.


11
Evet, yük test aşamasında yapılmalıdır
Alvaro

152
Yavaş parçaların nerede olduğunu bilmeden önce optimizasyon, erken optimizasyondur. Yavaş parçaların nerede olduğunu bilmeden önce o şeyi serbest bırakmak , erken salınmaktır !
Matematiksel

4
@MathematicalOrchid: Harika bir ifade! Başka bir yerden ödünç alabilir miyim?
Pieter Geerkens

3
@ PieterGeerkens Tabii, kendini nakavt! ;-) Sadece üzüldüm, 91+ olumlu oylar bana herhangi bir itibar kazandırmaz ... heh.
Matematiksel

3
@ Matematiksel Orkide bir cevap olmalıydı. Şimdiye kadar "en küçük noktadan noktaya" cevabı için koşabilir.
Mindwin

48

yayınlandığında yavaş sorguları izlemek

çünkü hiçbir şey kalitenizi, kullanıcılarınızın tasarım eksikliğinden dolayı acı çektirmesi demek değildir!

Tabloları tasarlarken hangi sorguların indekslere ihtiyacı olduğunu bilmelisiniz, hangi cümleciklerin ve birleşme noktalarının hangi sütunlarda sorgulandığını bilmelisiniz. Bunların önceden indekslenmesi gerekir; çünkü canlı bir ortamda belirgin olmayan şeyler, depolanan yük veya veri arttığında hızlı bir şekilde ortaya çıkabilir. Bu olduğunda yapmak istemediğiniz şey, her 'yavaş' sorguya indeksler koymak, her şeyde bir indeksle sonuçlanacak.


10
Sağ. Dizinleri veritabanı tasarımının bir parçası olarak düşünün. Son kullanıcının genellikle gerçek zamanlı olarak gerçekleştireceği herhangi bir sorgu için tam tablo taramasından kaçınmak için dizinleri kullanın.
AE

1
@DocBrown Bir masa tasarlarken, nasıl kullanılacağını anladığınızdan (ya da olması gerektiğinden) emin değilim. Bir kişilik masa kimliği veya soyadı tarafından sorgulanacaktır. Birisi DoB, adres veya telefon numarası ile erişmeye başlarsa, o zaman her alan için dizin ekleyeceksiniz - ve bu nerede bitiyor ?!
gbjbaanb

4
@gbjbaanb: insanlar ürününüze özellikler eklemeyi bıraktıklarında biter, ki bu sizin metodolojinize bağlı olarak “asla” olmayabilir.
Steve Jessop

1
@SteveJessop Ben erişmek istediğiniz birincil sütunlara göre indeks demek. Bir kişi tablosu için, bir arama işlevine sahip olabilirsiniz (örneğin, kullanıcı adınızı unutursanız, örneğin e-posta ile arayabilirsiniz), ancak daha sonra her zaman kimliği kullanırsınız. Yani ID endeksleme ihtiyacı olan tek kişidir. Diğer alanlarda çok fazla araştırma yaparsanız, bir dizin isteyebilirsiniz, bu zamanla ortaya çıkar, ancak genellikle birileri standart olmayan bir sorgu yazmaya karar verdiğinden dolayı, her sütunu dizinlemek istemezsiniz, ancak bu "bir defalık" durumlar için farklı bir mekanizma kullanır.
gbjbaanb

2
@gbjbaanb: elbette, insanlar, aynı soyadını, masa için uygun anahtardan daha az kullanmaları için marjinal olarak daha uygun bir tutamaç olduğu için bir masada aynı soyadı aramamalı . Tablonun soyadıyla endeksli olup olmadığı, aslında, "hepsinin aynı kullanıcı" üzerinde çalıştığını varsayan ancak kodunu tamamen ifade edemediğini belirten bir kod dizisi hakkında çok balıklı bir şey olduğu için söyleyeceğim. kodunu hatırlayarak koddayım :-) Müşteriden bahsedene kadar geriye doğru arama ihtiyacının beklenmediği durumları hayal ediyordum ...
Steve Jessop

26

“Erken optimizasyon”, aşağılayıcı anlamında, gerekmeyebilecek maliyetli optimizasyon anlamına gelir. O değil iflas önlemek için olası en geç noktasından önce uygulanan tüm optimizasyon demek!

Özellikle, uygulamanızın tamamen emmemesi için bazı makul (yaklaşık da olsa) gereklilikleri karşılayabileceğinizden emin olmak için, yayınlanmadan önce performans testlerine dayalı olarak optimize etmek meşrudur.

Mutlak bir asgari düzeyde , veritabanınıza makul miktarda test verisi yüklemeli ve uygulamanızın yanıt verebilirliğini kontrol etmelisiniz. Bu erken değil, çünkü bunun olacağını biliyorsunuz ve saçma sapan taramaları tetikleyen herhangi bir sorguyu yakalayacaktır. AE'nin dediği gibi bir yorum:

Son kullanıcının genellikle gerçek zamanlı olarak gerçekleştireceği herhangi bir sorgu için tam tablo taramasından kaçınmak için dizinleri kullanın

En azından, kullanımda büyümesi planlanan masalar için.

Daha sonra, bunun bir kısayolu olarak, veritabanı motoruyla ilgili önemli bir deneyime sahipseniz ve kodun ilk bölümünü yazarken testleri zaten planladıysanız, o zaman genellikle sorgunuzu çalıştırmadan bile bunu bileceksiniz İndeks olmadan yazı çok yavaş olacak. Tabii ki bilmiyormuş gibi davranmakta özgürsünüz ve testin geçmesi için dizini eklemeden önce başarısız olduğunu izliyorsunuz, ancak bilinen hatalı kodun (yanıt vermediğinden) yayına girmesi için bir neden yok.


20

Bunun erken optimizasyon olduğunu düşünüyorum çünkü uygulamamız henüz yayınlanmadı. Canlı yayına girdikten sonra yavaş sorguları izlemeyi ve ardından buna göre indeksler eklemeyi önerdim.

Son kullanıcılarınıza ve üretim ortamınıza kalite güvencesi gibi davranamazsınız. Daha fazla deyişle, üretimde çözeceğinizi söylüyorsunuz. Bunun doğru yol olduğunu sanmıyorum ve bu yaklaşımın her gün çok yanlış gittiğini görüyorum .

Bunu geniş bir fırçayla boyayamayacağınız için bir şeyi aklınızda tutmanız gerekir.

Senin ne ortak iş yükü ?

Bu çok açık veya donuk gelebilir, ancak pratikte önemlidir. İş yükünüzün% 98'ini oluşturan 10 sorunuz varsa (oldukça yaygındır, ister inanın ister inanmayın), tavsiyem üretim öncesi zor bir analiz olacaktır . Gerçekçi ve temsili verilerle, bu 10 sorgunun olabildiğince iyi olduğundan emin olun ( mükemmel , değerli zaman kaybıdır ve neredeyse elde edilemez).

İçin iş yükü% 2 oluşturan diğer 200 sorguları , o büyük olasılıkla çaba bir ton değerinde değildir ve üretimde sorun giderme tuhaflıklar perf köşe dava yapacak olanlardır. Bu aynı zamanda bir gerçeklik ve çok da kötü bir şey değil. Ancak bu, en iyi uygulamaların endekslenmesini göz ardı etmek veya veri alımı konusunda tahmini varsayımlarda bulunmak anlamına gelmez.

Üretimden önce veri tabanı performansını belirlemek yaygın ve iyi bir uygulamadır. Aslında, bu gelişme DBA adı verilen bu tür bir şey için nispeten ortak bir konum var .

Fakat...

Bazıları bunu çok ileri götürür ve "sadece durumda" diye endeksler ekleyerek çıldırır. Birisi bunun eksik bir indeks olduğunu öneriyor? Ve diğer dört varyasyon ekleyin. Aynı zamanda kötü bir fikir. Sadece veri almayı düşünmek zorunda değilsiniz, peki ya veri modifikasyonu? Tabloda ne kadar fazla indeks varsa, genellikle veriyi değiştirdiğinizde o kadar fazla ek yük demektir.

Çoğu şey gibi, sağlıklı bir denge var.

Eğlenceli küçük bir not olarak ... "Index" çoğullaştırması

"Endeksler" finansal insanlar içindir

"Dizinler" bizim için


2
Bunun için daha fazla oy gerekiyor. Daha fazla katılamadım.
RubberDuck

"Her ihtimale karşı" biraz 1 (yani ediyorum erken optimizasyon olun). Yapabilseydim, "ortak iş yükü" bitini tekrar oylayabilirdim.
David,

Umarım önceden hangisinin% 98'ine karşılık geldiğini ve hangilerinin olmadığını önceden biliyorsunuzdur.
Paŭlo Ebermann

@ PaŭloEbermann Çoğu DBMS, bu bilgiyi oldukça hızlı ve kolay bir şekilde yakalayabiliyor. Bu durumda, bilmemek için hiçbir bahane yoktur.
Thomas Stringer

@ThomasStringer Elbette, bu yalnızca üretime geçmeden önceki test durumlarınız bir şekilde üretimdeki gerçek kullanıcılar tarafından yapılanlarla ilgili olduğunda çalışır.
Paŭlo Ebermann

4

Hayır, erken optimizasyon değil, ancak herhangi bir optimizasyonun gerektiği gibi yapılması gerekiyor.

İşte ne yapardım:

  1. Bir üretim yükünü taklit etmek için veritabanını yeterli test verisiyle yükleyin. Bu% 100 kesinliği elde edemezsiniz ancak sorun değil: sadece yeterince veri koyun. Bir tabloda sabit miktarda veri var mı? Yükle. Çok fazla veri içeren bir tablonuz var mı, örneğin, bu sitedeki soruları içeren tablo ne? Yalnızca sahte veriler olsa bile birkaç milyon kaydı yükleyin.
  2. Veritabanı sunucunuzdaki profili açın .
  3. Otomatikleştirilmiş komut dosyaları (ses sağlar) ve gerçek kullanıcılar (bir şeyleri nasıl kıracaklarını biliyorlar) kombinasyonunu kullanarak uygulamadan uzak durun.
  4. Profil verilerini gözden geçirin. Belirli sorgular yavaş mı? Açıklama planlarını kontrol edin ve veritabanı sunucusunun bir dizin istediğini ancak var olmadığını söyleyip söylemediğini kontrol edin .

Veritabanı sunucuları karmaşık ve akıllı yazılım parçalarıdır. Nasıl dinleyeceğinizi biliyorsanız, nasıl optimize edeceğinizi söyleyebilirler.

Anahtarlar, optimizasyondan önce ve sonra performansı ölçmek ve veritabanının neye ihtiyacı olduğunu size bildirmesini sağlamaktır .


3

Bilinen sorunlar için kanıtlanmış kalıpları takip etmek (kimliğine göre bir kayıt bulmak gibi) erken bir şey değildir. Sadece mantıklı.

Bununla birlikte, endeksler her zaman basit bir iş değildir. Tasarım aşamasında, trafiğinizi hangi endekse bağlı olduğunu ve hangi yazma işlemlerini azaltacağını bilmek genellikle zordur. Bu yüzden, bazı "bariz" şema tasarımı en iyi uygulamalarından yararlanmayı savunuyorum (tasarlanmış okuma / yazma modellerine uygun PK'ları kullanın ve FK endeksini kullanın); ancak, stres testiniz talep edene kadar başka hiçbir şeye endeks koymayın.


Performansı arttırmak için neredeyse kesin olan ve "erken optimizasyon" değildir. Zarar vermesi çok düşük bir şey yapmak için fazladan 30 saniye harcamak. Bir tablodaki işlemlerin% 90'ı anahtar olarak belirli bir sütunu kullanıyorsa, dizine ekleme işlemi performansı artıracak veya performans hiçbir zaman yeterince yavaş olmayacaktır ve dizini oluşturmak için kod eklemek, işlemin yapılıp yapılmadığını belirlemekten daha az zaman alabilir gerçekten gerekli.
supercat

@supercat "never" ... Üretim ortamınızdaki kilitlenmeleri görmeye başlayana kadar ...
svidgen

Bir sütunu anahtar olarak kullanan işlemlerin% 90'ı ile tutarlı olacak ve bir dizin eklemenin kilitlenmeye neden olacağı hangi gerçekçi senaryoları öngörüyorsunuz?
supercat

@supercat Görevinizi tam olarak anladığımdan emin değilim. Aktif uygulama açısından, uygulama süresindeki veya ios sayısındaki hemen hemen herhangi bir artış kilitlenmelere neden olma potansiyeline sahiptir. ... Ancak, daha önemlisi, çoğu uygulamada bir endeksin varlığı veya yokluğu , veritabanı kritik bir boyuta ve / veya eşzamanlılık seviyesine ulaşana kadar ihmal edilebilir. Örneğin, tüm dizinleriniz artık belleğe sığmıyorsa ...
svidgen

1
Mesele şu ki, sorgu makyajınızın ne olduğunu bilmek zor, tipik kullanım durumları bir stres testinden geçinceye kadar (veya üretimde beklenmeyen kullanıcı davranışlarıyla ilgili sorunlar görene kadar). Eğer tablex.fieldy'i kilitleyen bir sayfanız varsa, ancak her bin kesici uç için sadece bir kez vuruldu ... Dizin net bir bozulmaya neden olabilir.
svidgen

2

Başvurunuz serbest bırakıldığında, çok geç.

Ancak herhangi bir uygun geliştirme süreci performans testlerini içermelidir.

Hangi endekslerin ekleneceğine karar vermek için performans testlerinizin sonuçlarını kullanın ve performans testlerini tekrarlayarak etkinliklerini doğrulayın.


Bir uygulama yayınlandığında, endeksleri değiştirmek için gerçekten iyi bir zamandır. Bu siteye bakın, stachexchange, şapkanız indeksler canlı yayına girdikten uzun süre sonra değiştiğini iddia edebilirsiniz.
LosManos

@LosManos: Kimse Stack Exchange'i kullanmak için para ödemez.
Monica ile

@LightnessRacesinOrbit: O çelişkili, reklamverenler Stack Exchange'i kullanmak için para ödüyorlar.

@JonofAllTrades: Eksik bir indeks nedeniyle birkaç saat boyunca düşük performans göstermememiz umrunda değil. Demek istediğim, sürekli bir dağıtım döngüsüne sahip, kullanımı kolay, geniş, topluluk odaklı bir web sitesinin, periyodik olarak yayınlanan, bağımsız bir ticari üründen çok farklı olduğu. Dolayısıyla, SE iyi bir örnek değildir.
Monica ile

1

Her sorgunun optimize edilmesi gerektiğini düşünmeme rağmen, indeksler RDBMS'nin bir parçası, yayınlanmadan önce dikkate alınması gerekenler. Bir sorgu yürüttüğünüzde, diğer programlama türlerinin aksine sisteme nasıl çalıştırılacağını anlatmazsınız. Kendi planları geliştiriyorlar ve neredeyse her zaman bir endeks kullanılabilirliğine dayanıyorlar. Verilerin yapısı ve hacmi daha sonraki zamanlarda da dikkate alınacaktır.

İşte göz önünde bulundurmam gereken bazı şeyler:

  1. Erken gelişiminizde sıkça kullanılacağını bildiğiniz bazı tanımlamalar yapmalısınız. Onlara odaklan.
  2. Yavaş sorgular olacak. Önce bunları dizine ekleyerek, performansın hala yeterince hızlı olup olmadığını belirleyebilir ve ardından yeniden tasarlamayı düşünebilirsiniz (Denormalizasyon erken olabilir). Serbest bırakılmadan önce bunu yapmayı tercih ederim. Hiç kimse envanterde bir şey bulmanın 10 dakika süreceği bir sistem istemez.
  3. Dizinler, sorgu performansını iyileştirebilir, ancak verilerin değiştirilmesini engellemez.
  4. Pek çok sistemde sorgularınızı analiz etmek için araçlar vardır, bu yüzden kullanmaktan korkmayın.

İlk incelemenizden sonra, bunu tekrar ne zaman gözden geçirmeniz gerektiği ve bunun için bilgileri nasıl toplayacağınız (kullanımı izlemek, müşteri verilerinin kopyalarını almak, vb.) İle ilgili bazı hususları dikkate almalısınız.

Erken optimizasyon yapmak istemediğinizi biliyorum, ancak veritabanınızı endekslemeden performansınızın düşük olacağı kesin. Bunu ortadan kaldırarak, performans sorunlarına neden olan başka alanlar olup olmadığını belirleyebilirsiniz.


0

Ayrıca, kaç tane kullanıcı beklediğinize de bağlıdır. Kesinlikle bazı yükleme testleri yapmalı ve veritabanınızın 10 - 100s ile 1000s arasındaki eşzamanlı istekleri karşılayabileceğinden emin olmalısınız. Yine, ne kadar trafik beklediğinize ve diğerlerinden daha çok hangi alanlarda kullanılmasını beklediğinize bağlıdır.

Genelde, kullanıcının en çok isabet etmesini beklediğim bölgelere ince ayar yapardım. Sonra kullanıcı deneyimi açısından yavaş olan her şeyi ayarlayabilirim. Kullanıcı ne zaman bir şey beklemek zorundaysa, kötü bir deneyim yaşar ve geri tepebilir. İyi değil!


0

Öncelikli bir analizle hangi sütunların kesinlikle bir endekse ihtiyaç duyduğunu belirlemek iyi bir uygulamadır. Kesinlikle endeksiniz yoksa veri tabanı büyüklüğü arttıkça üretimde kademeli veya beklenmedik performans düşme riski vardır. Kaçınılması gereken durum, yaygın olarak çalışan bir sorgunun çok sayıda tablo satırı taramasını gerektirdiği durumdur. Kritik sütunlara indeksler eklemek erken optimizasyon değildir, çünkü gerekli bilgilerin birçoğuna sahipsiniz ve potansiyel performans farkları önemlidir (büyüklük dereceleri). Endekslerin yararının verilere daha az net veya daha fazla bağımlı olduğu durumlar da vardır - muhtemelen bu vakaların bazıları için karar vermeyi erteleyebilirsiniz.

Sormanız gereken bazı sorular:

  • Her bir tablonun büyüklüğü için tasarım sınırları neler olacak?

Tablolar her zaman küçük olacaksa (<100 satır der), veritabanının tüm tabloyu taraması gerekiyorsa, felaket değildir. Bir dizin eklemek faydalı olabilir, ancak bu belirlemek için biraz daha uzmanlık veya ölçüm gerektirir.

  • Her sorgu ne sıklıkta çalıştırılacak ve gereken yanıt süresi nedir?

Sorgu nadiren çalıştırılıyorsa ve katı yanıt süresi gereksinimlerine sahip değilse (örneğin rapor oluşturma) ve satır sayısı çok büyük değilse, endeks eklemeyi ertelemek muhtemelen oldukça güvenlidir. Yine, uzmanlık veya ölçüm yararlı olup olmayacağını söylemeye yardımcı olabilir.

  • Sorgu, masanın birincil anahtardan başka bir şey tarafından aranmasını gerektiriyor mu? Örneğin tarih aralığına göre filtreleme, yabancı bir anahtara katılma?

Bu sorgular sık ​​sık çalıştırılıyorsa ve birçok satıra sahip tablolara dokunduysanız, o zaman ciddiyetle bir dizin eklemeyi düşünmelisiniz. Bunun bir sorgu için geçerli olup olmadığından emin değilseniz, veritabanını gerçekçi miktarda veriyle doldurabilirsiniz, ardından sorgu planına bakın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.