Performans ayarı gerektiren bir sorgunuz veya saklı yordamınız olduğunda, denediğiniz ilk şeylerden bazıları nelerdir?
Performans ayarı gerektiren bir sorgunuz veya saklı yordamınız olduğunda, denediğiniz ilk şeylerden bazıları nelerdir?
Yanıtlar:
İşte bana optimizasyon hakkında soran birine her zaman verdiğim kullanışlı şeylerin listesi.
Esas olarak Sybase kullanıyoruz, ancak tavsiyelerin çoğu yönetim kurulu genelinde geçerli olacak.
Örneğin SQL Server, bir dizi performans izleme / ayarlama bitiyle birlikte gelir, ancak bunun gibi bir şeye sahip değilseniz (ve belki varsa bile), o zaman aşağıdakileri dikkate alırım ...
Gördüğüm sorunların% 99'u bir birleşime çok fazla tablo koymaktan kaynaklanıyor . Bunun çözümü, birleştirmenin yarısını yapmak (bazı tablolarla) ve sonuçları geçici bir tabloda önbelleğe almaktır. Ardından, bu geçici tabloya katılarak sorgunun geri kalanını yapın.
#temp
tablolar, @table
büyük hacimli (binlerce satır) değişkenlerden çok daha iyi performans gösterebilir .Biraz konu dışı ama bu konular üzerinde kontrolünüz varsa ...
Yüksek Düzey ve Yüksek Etki.
CREATE INDEX
Sizin WHERE
ve JOIN
cümlecikleriniz için mevcut indeksler olduğundan emin olun . Bu, veri erişimini büyük ölçüde hızlandıracaktır.
Ortamınız bir veri reyonu veya ambar ise, akla gelebilecek hemen her tür sorgu için dizinler bol miktarda bulunmalıdır.
Bir de işlem ortamında bu indeks bakım kaynaklarını aşağı sürükleyin değil böylece indekslerin sayısı alt ve bunların tanımları daha stratejik olmalıdır. (Dizin bakımı, bir dizinin yapraklarının, INSERT, UPDATE,
ve DELETE
işlemlerinde olduğu gibi temel tablodaki bir değişikliği yansıtacak şekilde değiştirilmesi gerektiğidir .)
Ayrıca, dizindeki alanların sırasına dikkat edin - bir alan ne kadar seçici (daha yüksek kardinalite) ise, dizinde o kadar erken görünmelidir. Örneğin, kullanılmış otomobilleri sorguladığınızı varsayalım:
SELECT i.make, i.model, i.price
FROM dbo.inventory i
WHERE i.color = 'red'
AND i.price BETWEEN 15000 AND 18000
Fiyat genellikle daha yüksek kardinaliteye sahiptir. Yalnızca birkaç düzine renk mevcut olabilir, ancak büyük olasılıkla binlerce farklı fiyat soruyor.
Bu dizin seçeneklerinden, idx01
sorguyu tatmin etmek için daha hızlı yol sağlar:
CREATE INDEX idx01 ON dbo.inventory (price, color)
CREATE INDEX idx02 ON dbo.inventory (color, price)
Bunun nedeni, renk seçiminden daha az arabanın fiyat noktasını karşılaması ve sorgu motoruna analiz edilecek çok daha az veri vermesidir.
Birinde sorguları (ad, soyad) ve diğerinde (soyad, ad) hızlandırmak için yalnızca alan sıralamasında farklılık gösteren çok benzer iki dizine sahip olduğum biliniyor.
Yakın zamanda öğrendiğim bir numara, SQL Server'ın bir güncelleme ifadesinde yerel değişkenleri ve alanları güncelleyebilmesidir.
UPDATE table
SET @variable = column = @variable + otherColumn
Veya daha okunaklı versiyon:
UPDATE table
SET
@variable = @variable + otherColumn,
column = @variable
Bunu, yinelemeli hesaplamaları uygularken karmaşık imleçleri / birleştirmeleri değiştirmek için kullandım ve ayrıca performansta çok şey kazandım.
Performansta harika iyileştirmeler yapan ayrıntılar ve örnek kod: http://geekswithblogs.net/Rhames/archive/2008/10/28/calculating-running-totals-in-sql-server-2005---the-optimal. aspx
Burada MySQL olduğunu varsayarsak, sorguda neler olup bittiğini öğrenmek için EXPLAIN kullanın, dizinlerin olabildiğince verimli kullanıldığından emin olun ve dosya sıralarını ortadan kaldırmaya çalışın. High Performance MySQL: Optimization, Backups, Replication ve More , MySQL Performance Blog'da olduğu gibi bu konuda harika bir kitaptır .
@Terrapin isnull ve coalesce arasında bahsetmeye değer birkaç fark daha var (benim için önemli olan ANSI uyumluluğunun yanı sıra).
Genelde birleşimlerle başlayacağım - her birini teker teker sorgudan çıkaracağım ve sorun yaşadığım belirli bir birleşim varsa bir fikir edinmek için sorguyu yeniden çalıştıracağım.
Tüm geçici tablolarımda, indeksler yapmak için benzersiz kısıtlamalar (uygun olduğunda) ve birincil anahtarlar (neredeyse her zaman) eklemeyi seviyorum.
declare @temp table(
RowID int not null identity(1,1) primary key,
SomeUniqueColumn varchar(25) not null,
SomeNotUniqueColumn varchar(50) null,
unique(SomeUniqueColumn)
)
Her zaman bağlama değişkenlerini kullanmayı alışkanlık haline getirdim. RDBMS SQL ifadelerini önbelleğe almazsa, olası bağlama değişkenleri yardımcı olmaz. Ancak bağlama değişkenlerini kullanmazsanız, RDBMS'nin sorgu yürütme planlarını ve ayrıştırılmış SQL ifadelerini yeniden kullanma şansı yoktur. Tasarruf muazzam olabilir: http://www.akadia.com/services/ora_bind_variables.html . Çoğunlukla Oracle ile çalışıyorum, ancak Microsoft SQL Server hemen hemen aynı şekilde çalışıyor.
Tecrübelerime göre, bağlama değişkenlerini kullanıp kullanmadığınızı bilmiyorsanız, muhtemelen kullanmıyorsunuzdur. Uygulama diliniz bunları desteklemiyorsa, destekleyen bir tane bulun. Bazen B sorgusu için bağlama değişkenlerini kullanarak A sorgusunu düzeltebilirsiniz.
Bundan sonra, RDBMS'ye en çok neyin neden olduğunu bulmak için DBA'mızla konuşuyorum. "Bu sorgu neden yavaş?" Diye sormamanız gerektiğini unutmayın. Bu, doktorunuzdan ekinizi çıkarmasını istemek gibi bir şey. Sorgunuz sorun olabilir, ancak muhtemelen başka bir şeylerin ters gitmesi muhtemeldir. Geliştiriciler olarak, kod satırları açısından düşünme eğilimindeyiz. Bir çizgi yavaşsa, o satırı düzeltin. Ancak bir RDBMS gerçekten karmaşık bir sistemdir ve yavaş sorgunuz çok daha büyük bir sorunun belirtisi olabilir.
Çok fazla SQL ayarlama ipucu, kargo kült idolleri. Çoğu zaman sorun, kullandığınız sözdizimiyle ilgisiz veya çok az ilişkilidir, bu nedenle normalde yapabileceğiniz en temiz sözdizimini kullanmak en iyisidir. Ardından, veritabanını ayarlamanın yollarını aramaya başlayabilirsiniz (sorguyu değil). Sözdizimini yalnızca başarısız olduğunda değiştirin.
Herhangi bir performans ayarı gibi, her zaman anlamlı istatistikler toplayın. Ayarladığınız kullanıcı deneyimi olmadığı sürece duvar saati zamanını kullanmayın. Bunun yerine CPU zamanı, getirilen satırlar ve diskten okunan bloklar gibi şeylere bakın. Çoğu zaman insanlar yanlış şeyi optimize eder.
İLE (NoLock) kullanarak sorgu çalıştırmak benim yerime oldukça standart bir işlemdir. Onlarca gigabaytlık tablolarda sorgu çalıştırmadan yakalanan herkes çıkarılır ve vurulur.
Mümkünse NOT IN sorgularını LEFT OUTER JOINS'e dönüştürün. Örneğin, Tablo1'de bir yabancı anahtar tarafından kullanılmayan tüm satırları Tablo2'de bulmak istiyorsanız, şunu yapabilirsiniz:
SELECT *
FROM Table1
WHERE Table1.ID NOT IN (
SELECT Table1ID
FROM Table2)
Ancak bununla çok daha iyi performans elde edersiniz:
SELECT Table1.*
FROM Table1
LEFT OUTER JOIN Table2 ON Table1.ID = Table2.Table1ID
WHERE Table2.ID is null
Mutlaka bir SQL performans hilesi değil, kesinlikle ilişkili:
Önceden derlenmiş verileri veritabanından almak yerine doğrudan bellekten almak çok daha hızlı olacağından, mümkün olduğunda memcached'i kullanmak iyi bir fikir olabilir. Ayrıca yerleşik olarak memcached yapılan bir MySQL çeşidi de var (üçüncü taraf).
Dizin uzunluklarınızın olabildiğince küçük olduğundan emin olun. Bu, DB'nin dosya sisteminden bir seferde daha fazla anahtar okumasına izin verir, böylece birleşimlerinizi hızlandırır. Bunun tüm DB'lerle çalıştığını varsayıyorum, ancak bunun MySQL için özel bir öneri olduğunu biliyorum.
Bakıyorum:
SET NOCOUNT ON
Gerçekten kullanmam gerekmedikçe, genellikle depolanan prosedürlerimin içindeki ilk satır @@ROWCOUNT
.
SQL Server'da nolock yönergesini kullanın. Select komutunun beklemek zorunda kalmadan tamamlanmasını sağlar - genellikle diğer işlemlerin tamamlanması.
SELECT * FROM Orders (nolock) where UserName = 'momma'
Çok sayıda satırın işlevi çağıracağı Sprocs'taki işlev çağrılarını kaldırın.
Meslektaşım çok geniş kayıt kümeleri döndürmek için işlev çağrıları kullandı (örnek olarak userid'den lastlogindate alıyor).
Optimizasyonla görevlendirilen sproc'taki işlev çağrılarını işlevin koduyla değiştirdim: Birçok sprocs'un çalışma süresini> 20 saniyeden <1'e düşürdüm.
Kullanmayı severim
isnull(SomeColThatMayBeNull, '')
Bitmiş
coalesce(SomeColThatMayBeNull, '')
Birleşmenin size sağladığı çoklu argüman desteğine ihtiyacım olmadığında.
http://blog.falafel.com/2006/04/05/SQLServerArcanaISNULLVsCOALESCE.aspx
Depolanan Prosedür adlarının önüne "sp_" koymayın çünkü sistem prosedürlerinin tümü "sp_" ile başlar ve SQL Server, çağrıldığında prosedürünüzü bulmak için daha fazla arama yapmak zorunda kalacaktır.
set transaction isolation level read uncommitted
İşlem bütünlüğünün kesinlikle gerekli olmadığı durumlarda (bu genellikle doğrudur) ölü kilitleri önler