Recent comments

None


İçerik Ara











Yasal Uyarı
Bu sitede sunulan tüm bilgi ve dökümanlar Turgay Sahtiyan tarafından yazılmaktadır. Yazıların kaynak göstermek şartıyla kullanılması serbesttir.

© Copyright 2009-2013
Takvim
<<  Ağustos 2017  >>
PaSaÇaPeCuCuPa
31123456
78910111213
14151617181920
21222324252627
28293031123
45678910
Keywords

SQL Server Data Collector Hata - ODS - Get current snapshot of dm_exec_query_stats yazımda Data Collector de bulunan Query Statistics collection set inin verdiği “arithmetic overflow” hatasından bahsetmiş ve Microsoft’un bu hata çözümü için önerdiği yöntemin cumulative update 5 i yapmak olduğuna değinmiştim.

Cumulative update geniş ölçekli yapılarda evet diyilince yapılacak bir işlem değildir. Bu tarz güncelleştirmeler için sizin de firmanızda bazı prosedure ler bulunabilir. Ayrıca Microsoft dahi “ölümcül” bir hata olmadığı sürece cumulative update in production ortamına yapılmasını önermemektedir.

Bu yüzden bugünkü yazımda bahsi geçen hatayı cumulative update yapmadan “unsupported” bir yöntemle nasıl aşacağımızı anlatacağım. Unsported diyorum çünkü normalde bu hatanın çözümü için Microsoft cumulative update 5 in yapılmasını önermekte ve biz collection set in SSIS paketiyle oynayacağımız için bu durum unsupported bir durum oluşturmaktadır.

[more]

Bu kadar giriş cümlesinden sonra şimdi işleme dönelim. Dediğim gibi Query Statistics collection set inin SSIS paketinde oynama yapacağız ve hata veren kısmı çözmeye çalışacağız.

Bu collection set in upload işleminde hata olduğunu biliyorum. Dolayısıyla değişiklik yapacağım SSIS paket upload SSIS paketi olacak. Pakette değişiklik yapmak için Microsoft Visual Studio yu çalıştırıyorum.

File>>New>>Project>>Integration Service Project kısmından yeni bir Integration Service projesi başlatıyorum.

Clipboard01

SSIS Packages yazısına sağ tıklayıp Add Existing Package a tıklayalım.

Clipboard02

Gelen ekranda Server Name bilgisini yazarak ve Authentication Type ı seçerek Package Path in yanında bulunan butona basalım.

Clipboard03

Clipboard04

Değiştirmek istediğimiz paket olan QueryActivityUpload u seçerek OK e basalım. Bir önceki ekrandada OK e basalım ve ana ekrana düşelim.

Şimdi Solution Explorer kısmından bu paketi çift tıklayalım ve açalım.

Bizim hatamız DFT - Create Interesting Queries Upload Batch isimli Data Flow Task ta.

Clipboard05

Bu task ı çift tıklayarak Data Flow kısmına geçelim. Bu kısımda ise hata veren adım ODS - Get current snapshot of dm_exec_query_stats isimli OleDB Source ta.

Clipboard06

Bu objeyi çift tıklayarak properties ine erişelim.

Clipboard07

Şimdi can alıcı noktaya geliyoruz. Bu ekrandaki SQL Command ı alıp SSMS ten çalıştırdığınızda “arithmetic overflow” hatası alacaksınız. Dediğim gibi değişiklik yapacağımız kısım burası.

Hatanın sebebide 4 farklı satırda geçen aşağıdakine benzer çarpımlar.

r.total_elapsed_time * 1000 AS total_elapsed_time

 

Bu çarpım “arithmetic overflow” hatası vermekte. Cast kullanarak ufak bir trik le hatayı çözmeye çalışacağız.

cast(r.total_elapsed_time as float) * 1000 AS max_elapsed_time

 

Script in son hali aşağıdaki gibi olmalı.

SET NOCOUNT ON
DECLARE @p1 datetime
SET @p1 = GETDATE()

SELECT 
    [sql_handle],
    statement_start_offset,
    statement_end_offset,
    -- Use ISNULL here and in other columns to handle in-progress queries that are not yet in sys.dm_exec_query_stats.  
    -- These values only come from sys.dm_exec_query_stats. If the plan does not show up in sys.dm_exec_query_stats 
    -- (first execution of a still-in-progress query, visible in sys.dm_exec_requests), these values will be NULL. 
    MAX (plan_generation_num) AS plan_generation_num,
    plan_handle,
    MIN (creation_time) AS creation_time, 
    MAX (last_execution_time) AS last_execution_time,
    SUM (execution_count) AS execution_count,
    SUM (total_worker_time) AS total_worker_time,
    MIN (min_worker_time) AS min_worker_time,           -- NULLable
    MAX (max_worker_time) AS max_worker_time,
    SUM (total_physical_reads) AS total_physical_reads,
    MIN (min_physical_reads) AS min_physical_reads,     -- NULLable
    MAX (max_physical_reads) AS max_physical_reads,
    SUM (total_logical_writes) AS total_logical_writes,
    MIN (min_logical_writes) AS min_logical_writes,     -- NULLable
    MAX (max_logical_writes) AS max_logical_writes,
    SUM (total_logical_reads) AS total_logical_reads,
    MIN (min_logical_reads) AS min_logical_reads,       -- NULLable
    MAX (max_logical_reads) AS max_logical_reads,
    SUM (total_clr_time) AS total_clr_time,
    MIN (min_clr_time) AS min_clr_time,                 -- NULLable
    MAX (max_clr_time) AS max_clr_time,
    SUM (total_elapsed_time) AS total_elapsed_time,
    MIN (min_elapsed_time) AS min_elapsed_time,         -- NULLable
    MAX (max_elapsed_time) AS max_elapsed_time,
    @p1 AS collection_time
FROM
(
    SELECT  
        [sql_handle],
        statement_start_offset,
        statement_end_offset,
        plan_generation_num,
        plan_handle,
        creation_time,
        last_execution_time,
        execution_count,
        total_worker_time,
        min_worker_time,
        max_worker_time,
        total_physical_reads,
        min_physical_reads,
        max_physical_reads,
        total_logical_writes,
        min_logical_writes,
        max_logical_writes,
        total_logical_reads,
        min_logical_reads,
        max_logical_reads,
        total_clr_time,
        min_clr_time,
        max_clr_time,
        total_elapsed_time,
        min_elapsed_time,
        max_elapsed_time 
    FROM sys.dm_exec_query_stats AS q
    -- Temporary workaround for VSTS #91422.  This should be removed if/when sys.dm_exec_query_stats reflects in-progress queries. 
    UNION ALL 
    SELECT 
        r.[sql_handle],
        r.statement_start_offset,
        r.statement_end_offset,
        ISNULL (qs.plan_generation_num, 0) AS plan_generation_num,
        r.plan_handle,
        ISNULL (qs.creation_time, r.start_time) AS creation_time,
        r.start_time AS last_execution_time,
        1 AS execution_count,
        -- dm_exec_requests shows CPU time as ms, while dm_exec_query_stats 
        -- uses microseconds.  Convert ms to us. 
        --r.cpu_time * 1000 
        cast(r.cpu_time as float) * 1000 AS total_worker_time,
        qs.min_worker_time,     -- min should not be influenced by in-progress queries
        --r.cpu_time * 1000 
        cast(r.cpu_time as float) * 1000 AS max_worker_time,
        r.reads AS total_physical_reads,
        qs.min_physical_reads,  -- min should not be influenced by in-progress queries
        r.reads AS max_physical_reads,
        r.writes AS total_logical_writes,
        qs.min_logical_writes,  -- min should not be influenced by in-progress queries
        r.writes AS max_logical_writes,
        r.logical_reads AS total_logical_reads,
        qs.min_logical_reads,   -- min should not be influenced by in-progress queries
        r.logical_reads AS max_logical_reads,
        qs.total_clr_time,      -- CLR time is not available in dm_exec_requests
        qs.min_clr_time,        -- CLR time is not available in dm_exec_requests
        qs.max_clr_time,        -- CLR time is not available in dm_exec_requests
        -- dm_exec_requests shows elapsed time as ms, while dm_exec_query_stats 
        -- uses microseconds.  Convert ms to us. 
        --r.total_elapsed_time * 1000 
        cast(r.total_elapsed_time as float) * 1000 AS total_elapsed_time,
        qs.min_elapsed_time ,    -- min should not be influenced by in-progress queries
        --r.total_elapsed_time * 1000 
        cast(r.total_elapsed_time as float) * 1000 AS max_elapsed_time
    FROM sys.dm_exec_requests AS r 
    LEFT OUTER JOIN sys.dm_exec_query_stats AS qs ON r.plan_handle = qs.plan_handle AND r.statement_start_offset = qs.statement_start_offset 
        AND r.statement_end_offset = qs.statement_end_offset 
    WHERE r.sql_handle IS NOT NULL 
) AS query_stats 
OUTER APPLY sys.dm_exec_sql_text (sql_handle) AS sql
GROUP BY [sql_handle], plan_handle, statement_start_offset, statement_end_offset 
ORDER BY [sql_handle], plan_handle, statement_start_offset, statement_end_offset

 

İşimiz bitti. Bu ekranı OK diyerek kapatabiliriz. Daha sonrada değişiklik yaptığımız paketi save ediyoruz.

Şimdiki adımımız bu paketi hata aldığımız sunucuya deploy etmek.

Bunun için Integration Server a SSMS kullanarak bağlanıyoruz.

Clipboard08

Stored Packages >> MSDB >> Data Collector yazısına sağ tıklayıp Import Package ı seçiyoruz.

Clipboard09

Gerekli Import bilgilerini aşağıdaki gibi dolduruyorum ve paketi import ediyorum.

Clipboard10

Yapacaklarımız bu kadar :) Bende bu işlemlerden sonra collection set im şıkır şıkır çalışmaya başladı. Darısı sizin başınıza. :)

 

İyi çalışmalar

Turgay Sahtiyan

Not : Blog haricinde, faydali gördügüm yazilari ve linkleri twitter adresimden paylasiyorum. Beni twitter'da takip etmek için : twitter.com/turgaysahtiyan


Merhabalar,

Bu makalemde sizlere uzun zamandır yazmak istediğim bir konu olan SSIS deki FTP Task tan bahsedeceğim. FTP Task adından da anlaşılacağı gibi, SQL Server Integration servisinin ftp sunucuları ile iletişimini sağlayan bir kontrol akış nesnesi, peki bu nesne ne amaçlı kullanılabilir.

Örneğin sürekli veritabanında sakladığınız bazı bilgiler var ve siz bunları belli zaman aralıkları ile sorgular farklı bir dosya yapısında farklı lokasyonlara yüklemek isteyebilirsiniz, bu örnekte farklı lokasyon bir ftp sitesi olduğu durumlarda bu işi artık FTP Task kontrol akış nesnesi ile otomatik sağlayabilirsiniz. Şimdi bu senaryonun gerçekleştirimini bir örnek ile anlatalım.

[more]

Visual studiomuzu açıyoruz ve yeni bir “Integration Services” projesi oluşturuyoruz.

image001

Projemiz boş olarak açıldı, ilk olarak veri kaynaklarımızı hazırlıyoruz.

Solution explorer da bulunun data sources folderında sağ tuşa basarak new datasource a basıyoruz.

image002

Öncelikle verileri alacağım veri kaynağını tanımlıyorum.

image003

Şimdi bu bağlantıyı kullanarak SQL Server dan bir sorgu çalıştırıp bunun sonucunu bir text dosyaya aktaralım. Bunun için toolbox dan bir Data Flow Task nesnesi koyalım

image004

Şimdi bu data flow task içinden gerekli ayarlamalarımızı yapalım.

Data flow task nesnesine çift tıklayarak içine girelim ve bir OleDB Data Source nesnesi koyalım

image005

Bu OLE DB source nesnesini “select * from sys.databases” sorgusunu çalıştıracak şekilde ayarlayalım

Bunun için önce, daha önceden hazırladığımız ortak veri kaynaklarını paketimize import edelim.

image006

image007

Bu işlemden sonra Connection manager menüsünde aşağıdaki gibi ortak veri kaynağımızda tanımlanan nesneyi görmemiz gerekir

image008

Bu işlemlerden sonra OLEDB Soruce nesnemizi yapılandırabiliriz.

image009

Gerekli ayarlamalarımız yaptıktan sonra “OK” düğmesine basarak, hedef nesnemizi ayarlamaya başlayabiliriz.

Bunun için öncelikle bir “Flat File Destination” nesnesi tanımlıyorum.

image010

“Flat File Destination” nesnesi ile “OLE DB Soruce” nesnesini birbirine bağıyoruz. Ve “Flat File Destination” nesnesini yapılandırıyoruz.

image011

Not: Bu bu örnek için flat file ımı Delimited olarak ayarladım. Sizin tercihleriniz farklı olabnilir.

Öncelikle “Data Flow Task” nesnemi çalıştırtarak test ediyorum.

image012

image013

Şimdi “Control Flow” tabına dönerek bu oluşturduğum dosyayı bir ftp sunucuya yükleyeceğim. Bunun için ilk olarak paketime bir “FTP Task” nesnesi koyuyorum.

image014

Şimdi bu FTP nesnesinin ayarlamasını yapacağım.

FTP Task nesnesinin özelliklerine girdiğim zaman ilk olarak FTP nesnesinin connection özelliğini ayarlamam gerekiyor.

image015

New connection a basarak yeni bir FTP bağlantısı tanımlayacağım.

image016

Gerekli tanımlamalarımı yaptıktan sonra bağlantıyı test edebilirsiniz.

image017

image018

Bağlantı penceresini kapattıktan sonra File Transfer özelliklerinde daha önceden hazırladığımız Flat File nesnesini belirtmeliyiz.

image019

Local path özelliğine geldiğimizde çıkan listeden New Connection a tıklayarak gönderilecek dosyayı seçmeliyiz.

image020

image021

image022

Ok düğmesine basılarak FTP editörüne dönüp RemotePath özelliğini belirlemeliyiz.

Bu özellik ftp sunucusunda dosyayı upload edeceğimiz klasörü belirler, ben bu örneğimde ftp sunusunun root klasörüne veriyi koyacağımdan dolayı bu parametreyi “/” olarak belirliyorum.

image023

Bu seçimide yaptıktan sonra FTP task editör penceresinden ok düğmesine basarak çıkmalıyız.

Son olarak bu hazırladığımız FTP taskın akışını belirlemeliyiz.

image024

Artık paketimiz çalışır ve verileri kopyalar hale gelmiştir.

Şimdi paketimizi çalıştırarak ilgili dosyayı ftp sunucusuna yüklediğini görelim.

image025

Paketimiz başarı ile çalıştı, birde ftp sitesine giderek dosyanın yüklendiğini görelim.

image026

Şimdi ikinci örneğimde ilk örnekte oluşturulan paketin parametrik hale getirilmesinden bahsedeceğim.

Konfigürasyon tanımları için bir tablom var ve ftp sunucu bilgilerini bu bu tablodan belirlemek istiyorum, bu özellik bana değişen ftp sunucu bilgilerinin dinamik bir yapıda değiştirilebileceğinide gösteriyor olacak.

image027

Şimdi paketimde FTPServer ve RemotePath adında iki değişken yaratacağım.

image028

Paketin validasyonu için geçerli bir adres tanımladım, fakat çalışma zamanında bu değerleri veritabanından alıp değiştireceğim. Bunun için öncelikle FTP Connection nesnemin bu iki özelliğini bu değişkenden okumasını sağlamam gerekiyor.

Bunun için FTP connection nesnemin ve FTP task nesnemin özelliklerinden bu değerleri set etmeliyim.

Öncelikle FTP Connection Manager nesnemin Server Name parametresini set edeceğim.

image029

Expressions a tıklayarak çıkan pencerede bu özellikleri set edeceğim

image030

Burada dikkat edilmesi gereken husus ConnectionString set edilirken aşağıdaki kurallara uyulmalıdır.
FTPSunucu:FTPPort.UserName.Password

Daha sonra FTP task nesnesinin özelliklerinde “IsRemotePathVariable” = true yaparak bu nesnenin RemotePath özelliğini set edeceğim.

image031

Bu işlemide tamamladıktan sonra artık değerleri veritabanından set etmek için paketin en başına bir Execute SQL Task yerleştirip veritabanından okuduğum değerleri değişkene yazdıracağım.

Bunun için bir Execute SQL Task nesnesi yerleştirip, General tabında Result set “Single Row Set” yapıp ve aşağıdaki gibi bir sorgu yazıyorum.

image032

select 
FTPServer=(select convert(varchar(100),ConfigValue) from ConfigTable where ConfigName='FTP Server'),
RemotePath=(select convert(varchar(100),ConfigValue) from ConfigTable where ConfigName='Remote Path')

 

Result Set tabına geçip parametre atama işini gerçekleştireceğim.

image033

Artık paketim dinamik olarak çalışmaya hazırdır.

image034

 

İyi Çalışmalar

Kadir Evciler

Not : Blog haricinde, faydali gördügüm yazilari ve linkleri twitter adresimden paylasiyorum. Beni twitter'da takip etmek için : twitter.com/turgaysahtiyan