Aracılığıyla paylaş


JDBC sürücüsü için hazır ifade parametresi performansı

JDBC sürücüsünü indirin

Bu makalede, hazırlanmış deyim parametrelerinin SQL Server için Microsoft JDBC Sürücüsü'nde sunucu tarafı performansını nasıl etkilediği açıklanır ve parametre kullanımını iyileştirme konusunda rehberlik sağlanır.

Hazırlanan deyim parametrelerini anlama

Hazırlanan deyimler, SQL Server'ın bir sorguyu bir kez ayrıştırmasına, derlemesine ve iyileştirmesine, ardından yürütme planını birden çok kez yeniden kullanmasına olanak tanıyarak önemli performans avantajları sunar. Ancak, parametreleri belirtme şekliniz bu performans avantajını önemli ölçüde etkileyebilir.

Hazırlanmış bir deyim oluşturduğunuzda, SQL Server aşağıdakiler dahil olmak üzere parametre meta verilerini temel alan bir yürütme planı oluşturur:

  • Veri türü
  • Hassasiyet (sayısal türler için)
  • Ölçek (ondalık türleri için)
  • Uzunluk üst sınırı (dize ve ikili türler için)

SQL Server sorgu yürütme planını iyileştirmek için kullandığından bu meta veriler çok önemlidir. Bu parametre özelliklerinden herhangi birinde yapılan değişiklikler SQL Server'ı mevcut planı atmaya ve yeni bir plan oluşturmaya zorlayabilir ve bu da performans cezasına neden olur.

Parametre değişiklikleri performansı nasıl etkiler?

Parametre türü değişiklikleri

Hazırlanmış bir deyimin parametre türü yürütmeler arasında değiştiğinde, SQL Server deyimini yeniden hazırlamalıdır. Bu yeniden hazırlık şunları içerir:

  1. SQL deyimini yeniden ayrıştırma.
  2. Yeni bir yürütme planı derleme.
  3. Yeni planı önbelleğe alma (önbelleğe alma etkinse).

Aşağıdaki örneği inceleyin:

String sql = "SELECT * FROM Employees WHERE EmployeeID = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);

// First execution with Integer
pstmt.setInt(1, 100);
pstmt.executeQuery();

// Second execution with String - causes re-preparation
pstmt.setString(1, "100");
pstmt.executeQuery();

Bu senaryoda, setInt'dan setString'e geçiş, parametre türünü int'den varchar'e değiştirir ve bu da SQL Server'ı ifadeyi yeniden hazırlamaya zorlar.

Hassasiyet ve ölçek değişiklikleri

Numaralı türler için, c0 ve c1 gibi, duyarlık veya ölçek değişiklikleri de yeniden hazırlamayı tetikler.

String sql = "UPDATE Products SET Price = ? WHERE ProductID = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);

// First execution with specific precision
BigDecimal price1 = new BigDecimal("19.99"); // precision 4, scale 2
pstmt.setBigDecimal(1, price1);
pstmt.setInt(2, 1);
pstmt.executeUpdate();

// Second execution with different precision - causes re-preparation
BigDecimal price2 = new BigDecimal("1999.9999"); // precision 8, scale 4
pstmt.setBigDecimal(1, price2);
pstmt.setInt(2, 2);
pstmt.executeUpdate();

Duyarlık ve ölçek veritabanı altyapısının sorguyu nasıl işlediğini etkilediğinden, SQL Server farklı duyarlık ve ölçek birleşimleri için farklı yürütme planları oluşturur.

Parametre kullanımı için en iyi yöntemler

Hazırlanmış deyim performansını en üst düzeye çıkarmak için şu en iyi yöntemleri izleyin:

Parametre türlerini açıkça belirtin

Mümkün olduğunda, veritabanı sütun türlerinizle eşleşen açık ayarlayıcı yöntemlerini kullanın:

// Good: Explicit type matching
pstmt.setInt(1, employeeId);
pstmt.setString(2, name);
pstmt.setBigDecimal(3, salary);

// Avoid: Using setObject() without explicit types
pstmt.setObject(1, employeeId); // Type inference might vary

Tutarlı parametre meta verilerini kullanma

Sayısal parametreler için tutarlı duyarlığı ve ölçeği koruyun:

// Good: Consistent precision and scale
BigDecimal price1 = new BigDecimal("19.99").setScale(2);
BigDecimal price2 = new BigDecimal("29.99").setScale(2);

// Avoid: Varying precision and scale
BigDecimal price3 = new BigDecimal("19.9");    // scale 1
BigDecimal price4 = new BigDecimal("29.999");  // scale 3

Sayısal türlerle veri yuvarlamayı anlama

Sayısal parametreler için yanlış duyarlık ve ölçek kullanılması istenmeyen veri yuvarlamalarına neden olabilir. Hassasiyet ve ölçek, hem parametre değeri hem de SQL ifadesinde kullanıldığı yer için uygun olmalıdır.

// Example: Column defined as DECIMAL(10, 2)
// Good: Matching precision and scale
BigDecimal amount = new BigDecimal("12345.67").setScale(2, RoundingMode.HALF_UP);
pstmt.setBigDecimal(1, amount);

// Problem: Scale too high causes rounding
BigDecimal amount2 = new BigDecimal("12345.678"); // scale 3
pstmt.setBigDecimal(1, amount2); // Rounds to 12345.68

// Problem: Precision too high
BigDecimal amount3 = new BigDecimal("123456789.12"); // Exceeds precision
pstmt.setBigDecimal(1, amount3); // Might cause truncation or error

Verileriniz için uygun duyarlık ve ölçeklendirmeye ihtiyacınız olsa da, hazırlanan bir deyimin her yürütülmesi için bu değerleri değiştirmekten kaçının. Hassasiyet veya ölçekteki her değişiklik, sorgunun sunucuda yeniden hazırlanmasına neden olur ve hazırlanan sorguların performans avantajlarını ortadan kaldırır.

// Good: Consistent precision and scale across executions
PreparedStatement pstmt = conn.prepareStatement(
    "INSERT INTO Orders (OrderID, Amount) VALUES (?, ?)");

for (Order order : orders) {
    pstmt.setInt(1, order.getId());
    // Always use scale 2 for currency
    BigDecimal amount = order.getAmount().setScale(2, RoundingMode.HALF_UP);
    pstmt.setBigDecimal(2, amount);
    pstmt.executeUpdate();
}

// Avoid: Changing scale for each execution
for (Order order : orders) {
    pstmt.setInt(1, order.getId());
    // Different scale each time - causes re-preparation
    pstmt.setBigDecimal(2, order.getAmount()); // Variable scale
    pstmt.executeUpdate();
}

Doğruluğu ve performansı dengelemek için:

  1. İş gereksinimleriniz için uygun duyarlığı ve ölçeği belirleyin.
  2. Tutarlı duyarlık ve ölçek kullanmak için tüm parametre değerlerini normalleştirin.
  3. Değerlerin nasıl ayarlanacağını denetlemek için açık yuvarlama modlarını kullanın.
  4. Normalleştirilmiş değerlerinizin hedef sütun tanımlarıyla eşleşdiğini doğrulayın.

Uyarı

Parametre duyarlıklarını calcBigDecimalPrecision otomatik olarak iyileştirmek için bağlantı seçeneğini kullanabilirsiniz. Etkinleştirildiğinde, sürücü her BigDecimal değeri için gereken minimum duyarlığı hesaplar ve bu da gereksiz yuvarlamaların önlenmesine yardımcı olur. Ancak, farklı duyarlık değerleri yeniden hazırlığa neden olduğunda, veriler değiştikçe bu yaklaşım daha fazla deyim hazırlığı gerektirir. Uygulama kodunuzdaki en uygun duyarlığı ve ölçeği el ile tanımlamak, hem veri doğruluğu hem de tutarlı deyim yeniden kullanımı sağladığından mümkün olduğunda en iyi seçenektir.

Parametre ayarı yöntemlerini karıştırmaktan kaçının

Yürütmeler arasında aynı parametre konumu için farklı ayarlayıcı yöntemleri arasında geçiş yapmayın:

// Avoid: Mixing setter methods
pstmt.setInt(1, 100);
pstmt.executeQuery();

pstmt.setString(1, "100"); // Different method - causes re-preparation
pstmt.executeQuery();

setNull() öğesini açık türlerle kullanma

Null değerler ayarladığınızda tutarlılığı korumak için SQL türünü belirtin:

// Good: Explicit type for null
pstmt.setNull(1, java.sql.Types.INTEGER);

// Avoid: Generic null without type
pstmt.setObject(1, null); // Type might be inferred differently

Yeniden hazırlık sorunlarını algılama

Parametre değişikliklerinin performans sorunlarına neden olup olmadığını belirlemek için:

  1. SQL Server Profiler veya Genişletilmiş Olaylar'ı kullanarak SP:CacheMiss ve SP:Recompile olaylarını izleyin.
  2. sys.dm_exec_cached_plans Planın yeniden kullanılmasını denetlemek için DMV'yi gözden geçirin.
  3. Sık sık yeniden hazırlanan sorguları belirlemek için sorgu performansı ölçümlerini analiz edin.

Planın yeniden kullanılmasını denetlemek için örnek sorgu:

SELECT 
    text,
    usecounts,
    size_in_bytes,
    cacheobjtype,
    objtype
FROM sys.dm_exec_cached_plans AS cp
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) AS st
WHERE text LIKE '%YourQueryText%'
ORDER BY usecounts DESC;

Performans sayaçları

Şu SQL Server performans sayaçlarını izleyin:

  • SQL İstatistikleri: SQL Yeniden Derlemeleri/sn - Deyimlerin ne sıklıkta yeniden derlendiğini gösterir.
  • SQL İstatistikleri: SQL Derlemeleri/sn - Yeni planların ne sıklıkta oluşturulduğunu gösterir.
  • Plan Önbelleği: Önbellek İsabet Oranı - Planların ne kadar etkili bir şekilde yeniden kullanıldığını gösterir.

Sayaçlar ve bunların nasıl yorumleneceği hakkında daha fazla bilgi için bkz. SQL Server, Plan Cache nesnesi.

Gelişmiş dikkat edilmesi gerekenler

Parametreli sorgular ve plan önbelleği kirliliği

Plan önbelleği kirliliği, değişen ondalık veya sayısal duyarlık SQL Server'ın aynı sorgu için birden çok yürütme planı oluşturmasına neden olduğunda gerçekleşir. Bu sorun belleği boşa harcar ve plan yeniden kullanım verimliliğini azaltır:

// Avoid: Varying precision pollutes the plan cache
String sql = "UPDATE Products SET Price = ? WHERE ProductID = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);

for (int i = 0; i < 1000; i++) {
    // Each different precision/scale creates a separate cached plan
    BigDecimal price = new BigDecimal("19." + i); // Varying scale
    pstmt.setBigDecimal(1, price);
    pstmt.setInt(2, i);
    pstmt.executeUpdate();
}
pstmt.close();

Plan önbelleği kirliliğini önlemek için sayısal parametrelerde tutarlı bir şekilde kesinlik ve ölçeklemeyi koruyun.

// Good: Consistent precision and scale enables plan reuse
String sql = "UPDATE Products SET Price = ? WHERE ProductID = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);

for (int i = 0; i < 1000; i++) {
    // Same precision and scale - reuses the same cached plan
    // Note: Round or increase to a consistent scale that aligns with your application data needs.
    BigDecimal price = new BigDecimal("19." + i).setScale(2, RoundingMode.HALF_UP);
    pstmt.setBigDecimal(1, price);
    pstmt.setInt(2, i);
    pstmt.executeUpdate();
}
pstmt.close();

Dize uzunluğu ve tamsayı değeri varyasyonları plan önbelleği kirliliğine neden olmaz; yalnızca sayısal türler için duyarlık ve ölçek değişiklikleri bu sorunu oluşturur.

Bağlantı dizesi özellikleri

JDBC sürücüsü, hazırlanan deyim davranışını ve performansını etkileyen bağlantı özellikleri sağlar:

  • enablePrepareOnFirstPreparedStatementCall - (Varsayılan: false) Sürücünün birinci veya ikinci yürütmede çağırıp çağırmadığını sp_prepexec denetler. İlk yürütmeye hazırlanmak, bir uygulama aynı hazırlanmış deyimi birden çok kez tutarlı bir şekilde yürütürse performansı biraz artırır. İkinci yürütmeye hazırlanmak, çoğunlukla hazırlanmış deyimleri bir kez yürüten uygulamaların performansını artırır. Bu strateji, hazırlanan deyimin yalnızca bir kez yürütülmesi durumunda unprepare için ayrı bir çağrı gereksinimini ortadan kaldırır.
  • prepareMethod - (Varsayılan: prepexec) Hazırlık (prepare veya prepexec) için kullanılacak davranışı belirtir. prepareMethod'ın prepare olarak ayarlanması, yürütme planında veritabanının dikkate alacağı herhangi bir başlangıç değeri olmaksızın, deyimin hazırlanması için veritabanına ayrı ve ilk bir yolculuğa neden olur. prepexec hazırlama yöntemi olarak kullanılacak sp_prepexec şekilde ayarlayın. Bu yöntem, hazırlama eylemini ilk yürütme ile birleştirir ve ağ gidiş dönüşlerini azaltır. Ayrıca veritabanına, veritabanının yürütme planında göz önünde bulundurabileceği ilk parametre değerlerini de sağlar. Dizinlerinizin nasıl iyileştirildiğinden bağlı olarak, bir ayar diğerinden daha iyi performans gösterebilir.
  • serverPreparedStatementDiscardThreshold - (Varsayılan: 10) İşlemlerin sp_unprepare toplu işlenmesini kontrol eder. Bu seçenek, sp_unprepare çağrılarını toplu olarak toplayarak performansı artırabilir. Daha yüksek bir değer, hazırlık ifadelerini sunucuda daha uzun süre kalmasına neden olur.

Daha fazla bilgi için bkz. Bağlantı özelliklerini ayarlama.

Özet

Hazır ifadelerin parametreler için performansını iyileştirmek için:

  1. Veritabanı sütun türlerinizle eşleşen açık ayarlayıcı yöntemlerini kullanın.
  2. Yürütmeler arasında parametre meta verilerinin (tür, duyarlık, ölçek, uzunluk) tutarlı kalmasını sağlayın.
  3. Aynı parametre için farklı ayarlayıcı yöntemleri arasında geçiş yapmayın.
  4. setObject veya setNull kullanırken SQL türlerini açıkça belirtin.
  5. Yeni deyimler oluşturmak yerine hazırlanmış deyimleri yeniden kullanın.
  6. Yeniden hazırlık sorunlarını belirlemek için plan önbelleği istatistiklerini izleyin.
  7. Hazırlanan deyim performansını etkileyen bağlantı özelliklerini göz önünde bulundurun.

Bu uygulamaları izleyerek, sunucu tarafında yeniden hazırlığı en aza indirir ve hazırlıklı ifadelerden en iyi performans avantajlarını elde edersiniz.

Ayrıca bakınız

JDBC sürücüsü için hazır beyan meta verisi önbellekleme
JDBC sürücü ile performansı ve güvenilirliği artırma
Bağlantı özelliklerini ayarlama