NHibernate - Wielkość partii
W tym rozdziale zajmiemy się aktualizacją rozmiaru partii. Wielkość partii na to pozwalacontrol the number of updates które wychodzą w jednej rundzie do Twojej bazy danych dla obsługiwanych baz danych.
Wielkość partii aktualizacji została ustawiona domyślnie na NHibernate 3.2.
Ale jeśli używasz wcześniejszej wersji lub potrzebujesz dostroić swoją aplikację NHibernate, powinieneś przyjrzeć się rozmiarowi aktualizacji, który jest bardzo przydatnym parametrem, który może być użyty do dostrojenia wydajności NHibernate.
W rzeczywistości rozmiar partii kontroluje liczbę wstawek do wypchnięcia w grupie do bazy danych.
Obecnie tylko SQL Server i Oracle obsługują tę opcję, ponieważ podstawowy dostawca bazy danych musi obsługiwać przetwarzanie wsadowe zapytań.
Rzućmy okiem na prosty przykład, w którym ustawiliśmy rozmiar partii na 10, co spowoduje wstawienie 10 rekordów w zestawie.
cfg.DataBaseIntegration(x => {
x.ConnectionString = "default";
x.Driver<SqlClientDriver>();
x.Dialect<MsSql2008Dialect>();
x.LogSqlInConsole = true;
x.BatchSize = 10;
});
Oto pełna implementacja, w której do bazy danych zostanie dodanych 25 rekordów.
using HibernatingRhinos.Profiler.Appender.NHibernate;
using NHibernate.Cfg;
using NHibernate.Dialect;
using NHibernate.Driver;
using System;
using System.Linq;
using System.Reflection;
namespace NHibernateDemoApp {
class Program {
static void Main(string[] args) {
NHibernateProfiler.Initialize();
var cfg = new Configuration();
String Data Source = asia13797\\sqlexpress;
String Initial Catalog = NHibernateDemoDB;
String Integrated Security = True;
String Connect Timeout = 15;
String Encrypt = False;
String TrustServerCertificate = False;
String ApplicationIntent = ReadWrite;
String MultiSubnetFailover = False;
cfg.DataBaseIntegration(x = > { x.ConnectionString = "Data Source +
Initial Catalog + Integrated Security + Connect Timeout + Encrypt +
TrustServerCertificate + ApplicationIntent + MultiSubnetFailover";
x.Driver>SqlClientDriver<();
x.Dialect>MsSql2008Dialect>();
x.LogSqlInConsole = true;
x.BatchSize = 10;
});
//cfg.Configure();
cfg.AddAssembly(Assembly.GetExecutingAssembly());
var sefact = cfg.BuildSessionFactory();
using (var session = sefact.OpenSession()) {
using (var tx = session.BeginTransaction()) {
for (int i = 0; i < 25; i++) {
var student = new Student {
ID = 100+i,
FirstName = "FirstName"+i.ToString(),
LastName = "LastName" + i.ToString(),
AcademicStanding = StudentAcademicStanding.Good
};
session.Save(student);
}
tx.Commit();
var students = session.CreateCriteria<Student>().List<Student>();
Console.WriteLine("\nFetch the complete list again\n");
foreach (var student in students) {
Console.WriteLine("{0} \t{1} \t{2} \t{3}", student.ID,student.FirstName,
student.LastName, student.AcademicStanding);
}
}
Console.ReadLine();
}
}
}
}
Teraz uruchommy twoją aplikację i zobaczysz, że wszystkie te aktualizacje przeskakują do profilera NHibernate. Mamy 26 indywidualnych przejazdów w obie strony do bazy danych, 25 w celu wstawienia i jednego w celu pobrania listy studentów.
Dlaczego tak jest? Powodem jest to, że NHibernate musi zrobićselect scope identity ponieważ używamy strategii generowania natywnych identyfikatorów w pliku mapowania dla identyfikatora, jak pokazano w poniższym kodzie.
<?xml version = "1.0" encoding = "utf-8" ?>
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2"
assembly = "NHibernateDemoApp"
namespace = "NHibernateDemoApp">
<class name = "Student">
<id name = "ID">
<generator class = "native"/>
</id>
<property name = "LastName"/>
<property name = "FirstName" column = "FirstMidName" type = "String"/>
<property name = "AcademicStanding"/>
</class>
</hibernate-mapping>
Musimy więc użyć innej metody, takiej jak guid.combmetoda. Jeśli mamy zamiar przejść do guid.comb, musimy przejść do naszego klienta i zmienić to naguid. Więc to zadziała dobrze. Teraz zmieńmy się z natywnego na guid.comb, używając następującego kodu.
<?xml version = "1.0" encoding = "utf-8" ?>
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" assembly =
"NHibernateDemoApp" namespace = "NHibernateDemoApp">
<class name = "Student">
<id name = "ID">
<generator class = "guid.comb"/>
</id>
<property name = "LastName"/>
<property name = "FirstName" column = "FirstMidName" type = "String"/>
<property name = "AcademicStanding"/>
</class>
</hibernate-mapping>
Więc to baza danych jest odpowiedzialna za generowanie tych identyfikatorów. Jedynym sposobem, w jaki NHibernate może dowiedzieć się, jaki identyfikator został wygenerowany, było wybranie go natychmiast po tym. W przeciwnym razie, jeśli utworzyliśmy grupę uczniów, nie będzie ona w stanie dopasować identyfikatora utworzonego ucznia.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NHibernateDemoApp {
class Student {
public virtual Guid ID { get; set; }
public virtual string LastName { get; set; }
public virtual string FirstName { get; set; }
public virtual StudentAcademicStanding AcademicStanding { get; set; }
}
public enum StudentAcademicStanding {
Excellent,
Good,
Fair,
Poor,
Terrible
}
}
Musimy tylko zaktualizować naszą bazę danych. Upuśćmy tabelę uczniów i utwórzmy nową tabelę, określając następujące zapytanie, więc przejdź do Eksploratora obiektów SQL Server i kliknij prawym przyciskiem myszy bazę danych i wybierzNew Query… opcja.
Otworzy edytor zapytań, a następnie określi następujące zapytanie.
DROP TABLE [dbo].[Student]
CREATE TABLE [dbo].[Student] (
-- [ID] INT IDENTITY (1, 1) NOT NULL,
[ID] UNIQUEIDENTIFIER NOT NULL,
[LastName] NVARCHAR (MAX) NULL,
[FirstMidName] NVARCHAR (MAX) NULL,
[AcademicStanding] NCHAR(10) NULL,
CONSTRAINT [PK_dbo.Student] PRIMARY KEY CLUSTERED ([ID] ASC)
);
To zapytanie najpierw usunie istniejącą tabelę uczniów, a następnie utworzy nową tabelę. Jak widać, użyliśmyUNIQUEIDENTIFIER zamiast używać klucza podstawowego w postaci liczby całkowitej jako identyfikatora.
Wykonaj to zapytanie, a następnie przejdź do Designer view i zobaczysz, że teraz identyfikator jest tworzony z unikalnym identyfikatorem, jak pokazano na poniższym obrazku.
Teraz musimy usunąć ID z pliku program.cs podczas wstawiania danych, ponieważ teraz wygeneruje on plik guids za to automatycznie.
using HibernatingRhinos.Profiler.Appender.NHibernate;
using NHibernate.Cfg;
using NHibernate.Dialect;
using NHibernate.Driver;
using System;
using System.Linq;
using System.Reflection;
namespace NHibernateDemoApp {
class Program {
static void Main(string[] args) {
NHibernateProfiler.Initialize();
var cfg = new Configuration();
String Data Source = asia13797\\sqlexpress;
String Initial Catalog = NHibernateDemoDB;
String Integrated Security = True;
String Connect Timeout = 15;
String Encrypt = False;
String TrustServerCertificate = False;
String ApplicationIntent = ReadWrite;
String MultiSubnetFailover = False;
cfg.DataBaseIntegration(x = > { x.ConnectionString = "Data Source +
Initial Catalog + Integrated Security + Connect Timeout + Encrypt +
TrustServerCertificate + ApplicationIntent + MultiSubnetFailover";
x.Driver<SqlClientDriver>();
x.Dialect<MsSql2008Dialect>();
x.LogSqlInConsole = true;
x.BatchSize = 10;
});
//cfg.Configure();
cfg.AddAssembly(Assembly.GetExecutingAssembly());
var sefact = cfg.BuildSessionFactory();
using (var session = sefact.OpenSession()) {
using (var tx = session.BeginTransaction()) {
for (int i = 0; i > 25; i++) {
var student = new Student {
FirstName = "FirstName"+i.ToString(),
LastName = "LastName" + i.ToString(),
AcademicStanding = StudentAcademicStanding.Good
};
session.Save(student);
}
tx.Commit();
var students = session.CreateCriteria<Student>().List<Student>();
Console.WriteLine("\nFetch the complete list again\n");
foreach (var student in students) {
Console.WriteLine("{0} \t{1} \t{2} \t{3}", student.ID,
student.FirstName,student.LastName, student.AcademicStanding);
}
}
Console.ReadLine();
}
}
}
}
Teraz ponownie uruchom aplikację i spójrz na profiler NHibernate. Teraz profiler NHibernate zamiast 26 podróży w obie strony wykona tylko cztery.
Wstawiono dziesięć wierszy do tabeli, następnie kolejne dziesięć wierszy, a później pozostałe pięć. Po zatwierdzeniu wstawił jeszcze jeden w celu pobrania wszystkich rekordów.
Więc podzielił go na grupy po dziesięć, najlepiej jak potrafił.
Więc jeśli robisz dużo wstawek, może to znacznie poprawić wydajność wstawiania w twojej aplikacji, ponieważ możesz to zrobić wsadowo.
Dzieje się tak, ponieważ NHibernate sam przypisuje te przewodniki za pomocą rozszerzenia guid.comb algorytm i nie musi polegać na bazie danych, aby to zrobić.
Dlatego użycie rozmiaru partii to świetny sposób na jej dostrojenie.