27 Şubat 2014 Perşembe

HATA: Login failed for user ''. Reason: An attempt to login using SQL authentication failed...


HATA: 
Error: 18456, Severity: 14, State: 58.
Login failed for user ''. Reason: An attempt to login using SQL authentication failed. Server is configured for Windows authentication only.

AÇIKLAMA:
SQL Error Log'unda böyle bir hata ile karşılaşabilirsiniz. Keza bu giriş denemesini yapan kullanıcı da aşağıdaki gibi bir hata alacaktır:

Login failed for user ''.

Öncelikle bu hata biraz yanıltıcı aslında. Özellikle de hata mesajının ikinci cümlesi olan "Server is configured for Windows authentication only" cümlesinin bu hata ile hiçbir ilgisi yok. Çünkü bu hatayı "Mixed Mode Authentication" yani "SQL Authentication" olarak ayarlanmış bir SQL Server Instance'ında da alabiliyorsunuz!

Bu hatanın nasıl oluşabileceğini düşünürken aklıma bir fikir geldi ve bunu öncelikle SQL Server Management Studio (SSMS) ile denedim. Aklıma gelen fikir, bu hatanın SQL Authentication Mode ile fakat bir kullanıcı adı belirtmeden bağlanmaya çalışıldığında oluşabileceğiydi. SSMS ile yaptığım denemede aşağıdaki sonucu aldım:

SSMS ile kullanıcı bilgisi girmeden yaptığım test
Bu testte SQL Error Log'a herhangi bir kayıt düşmedi. Çünkü SSMS arayüzünden işleme devam etmek için onay alamadım! SSMS herhangi bir kullanıcı bilgisi girmeden SQL Authentication Mode ile bağlanamayacağımı anlayacak kadar akıllıydı. Ben de tam bu sırada VS ile bağlantı denemesi için küçük bir uygulama yazayım diye düşünürken, aklıma ODBC Client'ı geldi. ODBC Data Sources uygulamasını çalıştırdım ve User DSN bölümünden öylesine bir DSN kaydı oluşturdum.

ODBC Data Source ile yaptığım deneme


Tabii ki bağlantı yöntemi olarak SQL Authentication'ı seçtim ve kullanıcı adı bilgisini boş bıraktıktan sonra DSN oluşturma işlemine devam ettim ve voila! Bağlantı kuruldu ve hata alındı. Hata tam da beklediğim gibi bu şekilde alınmıştı. Anladım ki kullanıcı tarafında kullanılan uygulama, kullanıcı bilgilerinin girilip girilmediğini kontrol etmeden SQL Server Instance'ına bağlanmaya çalışıyordu ve bu nedenle ben de SQL Error Log'unda böyle bir hata mesajı görüyordum.

26 Şubat 2014 Çarşamba

sp_configure 'max degree of parallelism' kullanımında olası bir kriz anı!


Selam arkadaşlar,

Bir SQL Server Error Log dosyasını incelerken farkedip, sizlerle de paylaşmak istedim.

Bir SQL Server Instance'ının Max Degree of Parallelism ayarını (örneğin 1'den, yani seri çalışma şeklinden 4'e) değiştirdiğinizde SQL Server Error Log dosyasında aşağıdaki kaydı görürsünüz:

Configuration option 'max degree of parallelism' changed from 1 to 4. Run the RECONFIGURE statement to install.

Hemen bunun altında da aşağıdaki kayıtları görürsünüz:

SQL Server has encountered 1 occurrence(s) of cachestore flush for the 'Object Plans' cachestore (part of plan cache) due to some database maintenance or reconfigure operations.
SQL Server has encountered 1 occurrence(s) of cachestore flush for the 'SQL Plans' cachestore (part of plan cache) due to some database maintenance or reconfigure operations.
SQL Server has encountered 1 occurrence(s) of cachestore flush for the 'Bound Trees' cachestore (part of plan cache) due to some database maintenance or reconfigure operations.

Bu mesajlar, tüm Procedure Cache'inizin sıfırlandığı anlamına gelir. Yani hafızada bulunan tüm Execution Plan'lar artık yok, silindiler. Execution Plan oluşturma işinin de oldukça CPU maliyetli bir iş olduğunu düşünürsek, Max Degree of Parallelism gibi Procedure Cache'in temizlenmesine neden olan bir değişikliği operasyonun çok kritik olduğu bir zamanda yapmanın nasıl bir sonuç doğuracağının önceden farkında olmanız gerekir. Tabii ki buna özellikle de üretim ortamlarında dikkat etmek gerekiyor. 

Bu tarz sonuçlara neden olacak değişikliklerin yapılacağı zamanı iyi planlamalısınız. Ayrıca değişiklikten sonra gelebilecek "sistem çöktü!" veya "sistem çok ağır çalışıyor!" gibi şikayetlere de hazırlıklı olmalısınız. Çünkü yeni oluşacak bir Execution Plan, istisnai bir kayıt nedeniyle ilgili SP'nin genel çalışma beklentisine uymayacak bir şekilde derlenebilir ve bu da CPU, IO, RAM gibi kaynakların aşırı kullanımına ve yavaşlığa neden olabilir. Bu nedenle tetikte olmanızda büyük fayda var.

Kolay gelsin,
Ekrem Önsoy

20 Şubat 2014 Perşembe

Contained Databases


Selam arkadaşlar,

Size SQL Server 2012 ile birlikte gelen (ve belli ki arkası da gelecek olan) yeni bir özellikten, Contained Database özelliğinden bahsetmek istiyorum.

Bir cümlede anlatmaya çalışırsak, Contained Database'ler SQL Server Instance'ına bağımlı kalmadan, kendi kullanıcılarını (Login'lerini barındıran) ve bu sayede bir High Availibility yöntemiyle veya elle başka bir SQL Server Instance'ına taşındığında Login Mapping işleriyle uğraşmadan hemen kullanılabilecek veritabanlarıdır. 

SQL Server 2012 versiyonunda Contained Database özelliği kısmi olarak desteklenmekte (Containment = Partial), tam desteğin daha sonraki versiyonlarda geleceğine dair söylentiler var.

Daha da merak edenler için hemen veritabanlarının SQL Server Instance'ına bağımlılığı derken neyi kastettiğimi açıklayayım. Önceden de hatırlarsanız SQL Server'da kullanıcıların hem Instance düzeyinde (Login olarak) hem de veritabanı düzeyinde (User olarak) yaratıldığından ve yetkilendirildiğinden ayrıntılarıyla bahsetmiştim. Yeniden ve tek cümleyle hatırlatmak gerekirse, bir kullanıcının bir SQL Server veritabanına bağlanıp işlem yapabilmesi için öncelikle SQL Server Login'iyle SQL Server Instance'ına bağlanabilmesi ve Login'ine bağlanmış olan Database User'ı ile de veritabanına bağlanıp işlem yapabilmesi gerekiyor. Contained Database'lerde ise bir Login'e gerek kalmadan, Instance düzeyinde bir yetki denetimine tabi olunmadan doğrudan bir Database User ile veritabanına bağlanılıp işlemler yapılabiliyor.

Bir Contained Database oluştururken yine CREATE DATABASE komutunu kullanıyoruz, normal veritabanlarından farklı olarak ise sadece "CONTAINMENT = PARTIAL" parametrelerini aşağıdaki de ekliyoruz. Aşağıdaki kod ile "Veritabanim_contained" adında bir Contained Database oluşturmuş oluyoruz.

CREATE DATABASE [Veritabanim_contained] CONTAINMENT = PARTIAL

Hatırlarsanız bir veritabanı kullanıcısı (Database User) oluştururken aşağıdaki gibi bir komut kullanıyoruz:

CREATE USER [ekremo] FOR LOGIN [ekremo] WITH DEFAULT_SCHEMA=[dbo]

Bir Contained Database için ise aşağıdaki gibi bir kullanıcı da oluşturabiliyoruz:

CREATE USER [ekremo_contained] WITH PASSWORD=N'123456', DEFAULT_SCHEMA=[dbo]

Gördüğünüz gibi bu kullanıcının doğrudan kendi şifresi var ve bu veritabanına log in olurken bu bilgileri kullanarak log in olacak. Böylece hiç Instance seviyesinde bir güvenlik denetimi işlemi yapılmamış olacak. Doğrudan veritabanına log in olabilecek. Ben yukarıdaki örnekte nasıl bir şifreyle kullanıcı oluşturulacağını gösterdim, fakat bir Windows User'dan da, bir sertifikayla da Contained Database User oluşturulabilir.

Peki neden böyle bir ihtiyaç var? Yani birileri Login'lere gıcık mı oldu da o kadar uğraştı ve Contained Database diye bir şey icat etti? Tabii ki bunun oldukça geçerli bir nedeni var: High Availibility!

Bu konuda hiçbir bilgisi ve ilgisi olmayan arkadaşlarım için: "veritabanlarının a sunucusundan b sunucusuna otomatik olarak yedeklenmesi" diyebileceğim, meraklı arkadaşlarım için ise "Log ShippingDatabase Mirroring (artık Always On oluyor bu)Replication, Failover Clustering" gibi yöntemler sadece veritabanı düzeyinde kullanılan yöntemlerdir. Yani bu yöntemlerle SQL Server Instance düzeyindeki Login'ler, Linked Server'lar, SQL Server Agent Job'ları vd. nesneler aktarılmaz. Eğer Instance seviyesindeki bu nesnelerden uygulamanın çalışması için elzem olanlarının da otomatik olarak replike edilmesi için gerek 3. parti uygulamalarla gerekse Custom Script'lerle de bir çözüm bulunamazsa bu durumda a sunucusu kullanılamaz hale geldiğinde b sunucusuna otomatik olarak aktarılan / replike edilen veritabanları birisi müdahale etmeden kullanılamaz olacaktır. Contained Database'ler ise Instance'tan bağımsız veritabanları oldukları için, b sunucusu devreye girdiğinde otomatik olarak kullanılabilir olacaklar, en azından Login Mapping, Orphaned User gibi kullanıcı sorunları yaşanmayacaktır.

Bu yazıdan alıp gitmenizi istediğim en temel şey, artık x Instance'ından alınan/kopyalanılan bir veritabanının y Instance'ına aktarıldığında ekstra hiçbir şey yapılmasına gerek kalmadan çalışabilmesi için bir şeyler yapıldığından haberdar olmanız.

Ekrem Önsoy

18 Şubat 2014 Salı

SQL Server 2014 (CTP2)'de Öne Çıkan Yeniliklere Özet Bakış - 2

SQL Server 2014'teki yeni özellik ve yeteneklerden bahsetmeye devam ediyorum.

* Artık gerek Windows Azure'daki sanal makinenizde bulunan SQL Server veritabanlarının gerekse istediğiniz başka bir Veri Merkezindeki veya kendi sunucunuzdaki SQL Server veritabanlarınızın Data ve Transaction Log dosyalarını Windows Azure Blob Storage denilen yerde tutabilirsiniz.

Yani örneğin şirketinizin, fiziksel olarak da şirketinizde bulunan sunucularında yüklü olan SQL Server Instance'ınızda oluşturacağınız veritabanlarının Data ve Transaction Log dosyaları Windows Azure'un bulut ortamında barındırılabilir hale geliyor.

* Bir diğer yenilik, aslında SQL Server 2012 Service Pack 1, Cumulative Update 2 ile birlikte gelmişti. Bir veritabanının yedeğinin Windows Azure Blog Storage'ına alınabilmesinden bahsediyorum. Fakat bu versiyonda buluta yedek alma işlemi yalnızca T-SQL, Powershell ve SMO ile destekleniyordu. SQL Server 2014 ile birlikte bu özellik SQL Server Management Studio arayüzünden de yapılabilecek.

* Yine veritabanı yedeklemesiyle ilgili bir başka ve güzel yenilik ise artık veritabanları yedeklenirken aynı zamanda bir sertifika veya asimetrik anahtar ile şifrelenebilecek. Şifreleme algoritması olarak da şunlar destekleniyor: AES 128, AES 192, AES 256, and Triple DES.

16 Şubat 2014 Pazar

Bir Profiler Trace şablonu: TSQL_Duration

Selam millet!

Bu yazımda sizlere zaten birçoğunuzun gördüğü ve fakat büyük ihtimalle denemeden bile pas geçtiği bir şeyden bahsedeceğim. Bir Profiler Trace şablonu olan TSQL_Duration şablonundan (bkz Resim1).

Resim1


Bu şablonun en önemli özelliği Trace'i EventClass ve Duration alanlarıyla gruplandırması ve TextDate, SPID ve BinaryData alanlarıyla vermesi (bkz Resim2).


Resim2

 Peki neden özellikle bu şablondan bahsettim? Neden önemli (en azından bence)? Ne zaman önemli? Bunlardan bahsedeyim hemen.

Bu Trace çok pratik olarak sizlere o anda çalışıyor olan ve sıkıntılı olan işlemi söyleyecek. Anlık bir tespitte bulunmak için kullanılabilecek pratik bir yöntem. Örneğin aşağıdaki ekran görüntüsüne bakarsanız, en uzun süren işlemi hemen görebilirsiniz. Bu Trace o anda çalışıyor olan işlemleri gerçek zamanlı olarak gruplamaya ve en sıkıntılısını en altta göstermeye yarıyor (bkz Resim3).

Resim3
 Umarım işinize yarar!

Kolay gelsin,
Ekrem Önsoy



12 Şubat 2014 Çarşamba

HATA: An error occurred while executing batch. Error message is: Exception of type 'System.OutOfMemoryException' was thrown.

HATA: 
An error occurred while executing batch. Error message is: Exception of type 'System.OutOfMemoryException' was thrown.

AÇIKLAMA:
Bu hata tamamen Client uygulaması ile ilgili. Genelde de bu uygulama SQL Server Management Studio (SSMS) oluyor. Bu hata ile bizzat karşılaşmayalı uzun zaman olmuş. Genelde kullanıcılar bana bu hata ile gelirler ve ben de onlara "Yaptığınız SQL Server kurulumu 64Bit bile olsa, SSMS 32Bit bir uygulamadır bu nedenle kullanabileceği hafıza sınırlıdır. Eğer SSMS'te çok fazla sonuç döndüren bir soruyu çalıştırıyorsanız bu hata ile karşılaşabilirsiniz. Sorgu sonucunu Grid'e getirtmeyin, ya Text modunda yapın sorgulamayı ya da doğrudan dosyaya çıkarılsın sorgu sonucu" derim. Bugün bu hatayı bizzat kendim aldım ve çalıştırdığım sorgu çok da az bir sonuç dönüyordu. Buna rağmen bu hatayı almama ilk anda şaşırdım, sonra anladım nedenini. Neredeyse 20-25 tane Query Editor penceresi açıktı!

ÇÖZÜM:
SSMS'te eğer sorgu sonucunuz makul miktarda kayıt döndürüyor ve siz hala bu hata ile karşılaşıyorsanız, o zaman gereksiz Query Editor pencerelerini kapatmanızı öneririm. Benim sorunumu bu çözdü.

Eğer çok fazla kayıt döndüren bir sorgu çalıştırıyorsanız ve bu nedenle bu hata ile karşılaşıyorsanız o zaman da zaten çözümü yukarıdaki açıklama bölümünde paylaşmıştım.

10 Şubat 2014 Pazartesi

Inline TVF mı yoksa Multi Statement TVF mı? Mümkünse Inline lütfen!

Merhaba!


Size kısaca Inline (ITVF) ve Multi Statement Table Valued Function (MSTVF)'ların kullanımı ve farkından bahsetmek istiyorum.

Bugün bir sunucumuzda performans kontrolü yaparken bir sorgunun çok masraf oluşturduğunu gördüm. Sorguyu incelerken içerisinde bir Table Valued Function (TVF)'ın kullanıldığını fark ettim. Bu TVF'ı kontrol ederken, sadece bir sorgudan oluşan bir işlem olmasına rağmen MSTVF olarak aşağıdaki gibi yazıldığını gördüm (kritik bilgileri değiştirdim)

MSTVF
ALTER FUNCTION [dbo].[fTVFsorgu] (@degisken1 varchar(50))
RETURNS @TVF TABLE
(
Adres varchar(250)
,Belediye varchar(50)
,Mahalle varchar(50)
,Sokak varchar(50)
,islem_kodu int
)
AS
BEGIN
   INSERT @TVF
Select 
Adres
,Belediye
,Mahalle
,Sokak
,islem_kodu
FROM dbo.tablo_adi
WHERE AdSoyad=@degisken1
RETURN
END

Görüldüğü üzere bu TVF sadece bir sorgudan oluşuyor. 

Bazılarınızın "Peki bu tür sorguları ITVF olarak yazmakta fayda var? Fark nedir ki?" dediğinizi tahmin edebiliyorum. Şöyle ki, MSTVF'lardaki Table değişkenlerinin içinde kaç tane kayıt olursa olsun, SQL Server MSTVF'lardaki Table değişkenlerinin içinde sadece 1 tane kayıt olduğunu varsayar. MSTVF'ler SQL Server Query Optimizer için de bir karakutudur. Hal böyle olunca, uygun Index'lerden ve Statistic'lerden faydalanılamaz. Yani sorgu için Query Optimizer gerekli iyileştirme işlemlerini yapamaz.

Eğer TVF'ınınız içerisinde özellikle sadece bir Statement varsa çoğu zaman bunu ITVF'a çevirmenizde büyük fayda var. Eğer birden fazla Statement varsa da o zaman mümkünse bu Statement'ları birleştirip bir tane Statement şeklinde düzenleyip bu şekilde ITVF kullanmanız ve bu şekilde test etmeniz iyi olur.


ITVF
CREATE FUNCTION [dbo].[fTVFsorgu] (@degisken1 varchar(50))
RETURNS TABLE
AS
RETURN
Select 
Adres
,Belediye
,Mahalle
,Sokak
,islem_kodu
FROM dbo.tablo_adi
WHERE AdSoyad=@degisken1

Bu arada, eğer MSTVF ile ITVF'ın Execution Plan'larını doğrudan SQL Server Management Studio ile karşılaştıracak olursanız sizi yanıltabilecek bir sonuç ile karşılaşmanız kaçınılmaz. Çünkü burada MSTVF ile ilgili tablo üstünde yapılan IO işlemi dahil edilmiyor, fakat ITVF ile yapılan IO işlemleri dahil ediliyor. İlgili ekran görüntüsünü aşağıda görebilirsiniz:



Gördüğünüz gibi ITVF kullandığımızda artık bir karakutuyla (MSTVF) uğraşmamış oluyoruz ve tüm planı görebiliyoruz. Bu sayede en çok masraf oluşturan kalemleri de belirleyip gerekli aksiyonları alabiliyoruz. Bu örnekte ben Index'i Covered Index yapmadan önce aşağıdaki ITVF ilgili Index'teki alan için SEEK yaparken, diğer alanlar için Lookup yapıyordu ve bu da büyük bir IO masrafı oluşturuyordu. Fakat Index'i Covered Index yaptıktan sonra artık tamamen SEEK yapmaya başladı ve Query Optimizer da ITVF'daki sorguyu işleyebildiği için hemen bu Index'ten faydalandı ve performans çok arttı. Bu iyileşmenin sonucu için aşağıdaki ekran görüntüsüne bakabilirsiniz. 



Hem Index'in Covered Index'e çevrilmesiyle, hem de bu Function'ın MSTVF'dan ITVF'a çevrilerek Query Optimizer'ın bu sorguyu değerlendirip bu Index'ten faydalanılmasını sağlanmasıyla nasıl bir iyileşme yaşandığını görüyorsunuz. Uygun Index olmasına rağmen MSTVF bu Index'ten faydalanamıyor.

Kolay gelsin,
Ekrem Önsoy






Bir SQL Server veritabanının versiyonunu bulma

Selam!

Zaman zaman bir veritabanının versiyonunu bulmamız gerekebiliyor, özellikle de versiyonu daha yüksek olan bir veritabanını versiyonu daha düşük olan bir SQL Server Instance'ına Attach etmeye kalktığımızda ve aşağıdakine benzer bir hata ile karşılaştığımızda:

The database 'veritabanı_adı' cannot be opened because it is version 665. This server supports version 661 and earlier. A downgrade path is not supported.

Böyle bir hata ile karşılaştığımızda buradaki 661 ile (artık sizin ortamınızda ne olursa?) bizim Instance'ımızın versiyonu kastediliyor diye bunun hangi versiyon olduğunu az çok bildiğimizi düşünüyorum. Fakat 665 de nedir?

Maalesef bu veritabanı bilgileri Microsoft tarafından resmi olarak kayıt altında alınmadı, çünkü BOL'de de belirtildiği üzere bu bilgi Internal.

Bununla birlikte, sağolsun bir arkadaş bunları bir kenara not etmiş, ben de gerektiği anda ulaşabilelim diye burada değinmek istedim!

http://weblogs.sqlteam.com/dang/archive/2011/07/17/internal-sql-server-database-version-numbers.aspx

Bu Blog'da bir SQL Server 2012 veritabanın versiyonunun ne olduğu yazılı değil, bunu da ben eklemiş olayım:

SQL Server Version:                    Internal Database Version:
SQL Server 2012 + SP1                 706

Veritabanınızın versiyonunun ne olduğunu öğrenmek için aşağıdaki kodu kullanabilirsiniz:

SELECT DatabasePropertyex ('veritabanı_adı', 'version');

Bazı arkadaşlarım bu versiyon bilgisini SQL Server Instance versiyonu ile karıştırabilir diye aşağıdaki bilgiyi de paylaşmak istedim. SQL Server Instance'ının versiyon bilgisi aşağıdaki kod ile bulunabilir:

SELECT @@version

veya

SELECT SERVERPROPERTY('productversion')

Kolay gelsin,
Ekrem Önsoy

4 Şubat 2014 Salı

SQL Server 2014 (CTP2)'de Öne Çıkan Yeniliklere Özet Bakış - 1

Selam arkadaşlar,

Sizlerle birkaç yazıdan oluşan bir seri ile SQL Server 2014 Community Tehcnology Preview 2 (CTP2) sürümünde de bulunan ve şimdiye kadar açıklanan öne çıkmış bazı Database Engine özelliklerini paylaşmak istiyorum.

Bu ilk yazıda In-Memory OLTP'den bahsedeceğim.

"Hekaton" kod adıyla ortaya çıkan ve bazılarınca böyle kalması da istenen; fakat Microsoft tarafından "In-Memory OLTP" olarak adlandırılan, bildiğimiz Database Engine'e gömülmüş olan alternatif bir Engine dersek yanlış olmaz sanırım. Bildiğimiz klasik SQL Server Database Engine'ine tam olarak entegre edilmiştir. Şu anda halihazırda kullandığımız tablo ve SP yapılarına kıyasla birçooook limitasyonu bulunsa da, zamanla birçoğunun aşılacağına inanıyorum.

Bu yenilikle gelen şeyler temel olarak bir tablonun Memory Optimized Table (MOT) olarak oluşturulabilmesi. Bizim klasik tabloların da adları artık Disk Based Tables (DBT) oluverdi. MOT'lar temel olarak SQL Server servisi başlar başlamaz RAM'e yükleniyorlar. Bildiğiniz gibi DBT'lar, o tablolar üstünde işlem yapıldıkça yavaş yavaş yüklenirlerdi Buffer Pool'a, MOT'lar ile daha servis açılışında yükleniyorlar. Peki ne yararı var? diye sorarsanız hemen şöyle diyebilirim: MOT'lar için artık Blocking sorunu yaşamayacaksınız! Latch'miş, Lock'muş, artık yokmuş. Ayrıca MOT'lardaki verileri Durable olmak ve olmamak üzere saklayabiliyorsunuz. Eğer bir MOT'taki verileri Durable olmayacak şekilde saklarsanız o zaman o veriler ile ilgili işlemler sadece hafızada yapılıyor olacak ve diske işlenmeyecek. Veriler diske işlenmeyeceği için de hiç IO sorununuz olmayacak.


Peki bu teknolojiden en iyi hangi senaryolarda faydalanabilirsiniz? Birçok senaryo olabilir, fakat özellikle alışveriş sepeti, doldur boşalt, oturum yönetimi gibi senaryolar ilk aklıma gelenler; tabii ki çok daha yaratıcı olunabilir!


Tabii ki her tablo öyle kolayca MOT'a çevrilemiyor. Bu konuda bizlere kolaylık sağlayan AMR (http://msdn.microsoft.com/en-us/library/dn205133(v=sql.120).aspx) isimli bir Tool var, bu kullanılabilir. Hangi tabloların MOT'a, hangi SP'lerin Natively Compiled SP'ye çevrilebileceği konusunda fikir veriyor.

In-Memory OLTP ile gelen bir başka yenilik ise hemen bir üst pragrafta da bahsettiğim Natively Compiled SP'ler (NCSP). Bizim bildiğimiz klasik SP'lerin NCSP'ye çevrilmesiyle %70 oranında iyileştirmeler yaşandığını gördüm, Microsoft çok daha fazla iyileşme yaşanabileceğini söylüyor. Bu iyileşme de temel olarak hem MOT'ların NCSP ile daha entegre çalışabilmesinden hem de NCSP'lerin doğrudan C koduna çevrilip (bir SP NCSP'ye çevrildiğinde bu SP için NTFS'te bir *.dll dosyası oluşturuluyor) çok daha kestirme ve etkin bir şekilde çalıştırılıyor olmasından kaynaklanıyor.

Bu konuda şimdilik son olarak söylemek istediğim şey ise gerçekten çoook kısıtlama var! Kesinlikle bu teknolojiyi kullanmadan önce kısıtlamalarına bakmalısınız ve nasıl çalıştığını iyice anladığınızdan emin olmalısınız.