مطالب
چگونه کدها را مستند سازی کنیم؟
یکی از مهمترین مسائل، به خصوص در کارهای تیمی یا پروژه‌های اشتراکی، قرار دادن کامنت‌ها یا اصطلاحا مستند نویسی است که بسیاری از برنامه نویسان با اینکه نظریه آن‌را به شدت قبول دارند، ولی از انجام آن سرباز می‌زنند که به دو عامل تنبلی و عدم دانش نحوه‌ی مستند نویسی بر می‌گردد. در این مقاله قصد داریم به سوالات زیر پاسخ دهیم:
  • چرا به کامنت گذاری یا مستند نویسی نیاز داریم؟
  • چگونه کامنت بنویسیم؟
  • انواع کامنت‌ها چیست؟
  • چه کامنت‌هایی اشتباه هستند؟

همانطور که بیان کردیم، کامنت گذاری یکی از مهم‌ترین کارهایی است که یک برنامه نویس انجام می‌دهد. به خصوص زمانیکه به صورت تیمی کار می‌کنید، این امر مهم‌تر از قبل خود را نشان می‌دهد. بسیاری از برنامه نویسان که بیشتر دلیل آن تنبلی است، از این کار سرباز می‌زنند و ممکن است آن را اتلاف وقت بدانند. ولی با کامنت گذاری فهم و درک کد، در آینده بالا‌تر می‌رود. در مقاله‌ی تخصصی «هنر کامنت نویسی» نوشته‌ی «برنهارد اسپویدا» بهانه‌های جالبی از برنامه نویسان را برای سرباز زدن از اینکار، ذکر شده است؛ به عنوان نمونه:
من کدم را به خوبی متوجه می‌شوم.
کد خوب، خودش گویای همه چیز هست.
وقتی برای کامنت نویسی وجود ندارد. باید چسبید به کد.


سوالات زیر نیز دلیل این را که چرا باید کامنت گذاری کرد، مشخص می‌کنند:
  • شاید امروز معنای یک کد را متوجه شوید، ولی آیا در آینده، مثلا یک سال بعد هم چنین خواهد بود؟
  •  آیا می‌توانید هر سیستمی را که طراحی می‌کنید، به خاطر بسپارید که فعالیت‌هایش را به چه نحوی انجام می‌دهد؟
  • اگر در یک کار تیمی باشید، شاید شما متوجه کدتان می‌شوید، ولی آیا تضمینی وجود دارد که دیگران هم متوجه روش شما شوند؟
  • آیا کدی که شما بر روی آن فکر کرده‌اید و در ذهن خود روش انجام آن را ترسیم کرده‌اید، می‌تواند برای برنامه نویسی که کد شما را می‌بیند هم رخ دهد؟ 
  • اگر شما به صورت تیمی کاری را انجام دهید و یکی از برنامه نویس‌های شما از تیم جدا شود، چگونه می‌توانید کار او را دنبال کنید؟
  • اگر برای برنامه نویسی اتفاق یا حادثه‌ای پیش بیاید که دسترسی شما به او ممکن نباشد چه؟
کدی که مستند نشود، یا خوب مستند نشود، در اولین مرحله وقت شما یا هر فردی را که روی این کد کار می‌کند، برای مدتی طولانی می‌گیرد. در مرحله‌ی بعدی احتمالا مجبور هستید، کد را خط به خط دنبال کرده تا تاثیر آن را بر ورودی‌ها و خروجی‌ها ببینید. تمام این‌ها باعث هدر رفتن وقت شما شده و ممکن است این اتفاق برای هر تکه کدی رخ بدهد.


سطوح کامنت نویسی بر سه نوع هستند:

Documentary Comments:
این مستند سازی در سطح یک سند مثل فایل یا به خصوص یک پروژه رخ می‌دهد که شامل اطلاعات و تاریخچه‌ی آن سند است که این اطلاعات به شرح زیر هستند:

 File Name   نام سند
 File Number/Version Number   شماره نسخه آن سند
 Creation Date   تاریخ ایجاد آن
 Last Modification Date
 تاریخ آخرین تغییر سند
 Author's Name
 سازنده‌ی سند
 Copyright Notice
 اطلاعاتی در مورد کپی رایت سند
 Purpose Of Program
 هدف کاری برنامه. یک خلاصه از آن چه برنامه انجام می‌دهد.
 Change History
 لیستی از تغییرات مهمی که در جریان ایجاد آن رخ داده است.
 Dependencies  وابستگی‌های سند. بیشتر در سطح پروژه معنا پیدا می‌کند؛ مانند نمونه‌ی آن برای سایت جاری که به صورت عمومی منتشر شده است.
 Special Hardware Requirements
 سخت افزار مورد نیاز برای اجرای برنامه. حتی قسمتی می‌تواند شامل نیازمندی‌های نرم افزاری هم باشد.
نمونه ای از این مستند سازی برای برنامه ای که به زبان پاسکال نوشته شده است:
PCMBOAT5.PAS*************************************************************
**
File: PCMBOAT5.PAS
Author: B. Spuida
Date: 1.5.1999
Revision: 
1.1 
PCM-DAS08 and -16S/12 are supported.
Sorting routine inserted.
Set-files are read in and card as well as
amplification factor are parsed.

1.1.1
Standard deviation is calculated.

1.1.2
Median is output. Modal value is output.

1.1.4
Sign in Set-file is evaluated.
Individual values are no longer output.
(For tests with raw data use PCMRAW.EXE)

To do:
outliers routine to be revised.
Statistics routines need reworking.
Existing Datafile is backed up.

Purpose: 
Used for measurement of profiles using the
Water-SP-probes using the amplifier andthe PCM-DAS08-card, values are acquired
with n = 3000. Measurements are taken in 1
second intervals. The values are sorted using
Quicksort and are stacked "raw" as well as after
dismissing the highest and lowest 200 values as
'outliers'.


Requirements:
The Card must have an A/D-converter.
Amplifier and probes must be connected.
Analog Signal must be present.
CB.CFG must be in the directory specified by the
env-Variable "CBDIREC" or in present directory.

در بالا، خصوصیت کپی رایت حذف شده است. دلیل این امر این است که این برنامه برای استفاده در سطح داخلی یک شرکت استفاده می‌شود.


Functional Comments: کامنت نویسی در سطح کاربردی به این معنی نیست که شما اتفاقاتی را که در یک متد یا کلاس یا هر بخشی روی می‌دهد، خط به خط توضیح دهید؛ بلکه چرخه‌ی کاری آن شی را هم توضیح بدهید کفایت می‌کند. این مورد می‌تواند شامل این موارد باشد:
  • توضیحی در مورد باگ‌های این قسمت
  • یادداشت گذاری برای دیگر افراد تیم
  • احتمالاتی که برای بهبود ویژگی‌ها و کارایی کد وجود دارد.


Explanatory Comment: کامنت گذاری توصیفی در سطح کدنویسی رخ می‌دهد و شامل توضیح در مورد کارکرد یک شیء و توضیح کدهای شیء مربوطه می‌گردد. برای قرار دادن کامنت الزامی نیست که کدها را خط به خط توضیح دهید یا اینکه خطوط ساده را هم تشریح کنید؛ بلکه کامنت شما همینقدر که بتواند نحوه‌ی کارکرد هر چند خط کد مرتبط به هم را هم توضیح دهد، کافی است. این توضیح‌ها بیشتر شامل موارد زیر می‌شوند:

  • کدهای آغازین
  • کدهای خروجی
  • توضیح کوتاه از آنچه که این شیء ، متد یا ... انجام می‌دهد. 
  • حلقه‌های طولانی یا پیچیده
  • کدهای منطقی عجیب و پیچیده
  • Regular Expression

کدهای آغازین شروع خوبی برای تمرین خواهند بود. به عنوان نمونه اینکه توضیحی در مورد ورودی و خروجی یک متد بدهید که آرگومان‌های ورودی چه چیزهایی هستند و چه کاربری داردند و در آغاز برنامه، برنامه چگونه آماده سازی و اجرا می‌شود. مقادیر پیش فرض چه چیزهایی هستند و پروژه چگونه تنظیم و مقداردهی می‌شود.

کدهای خروجی هم به همین منوال است. خروجی‌های نرمال و غیرنرمال آن چیست؟ کدهای خطایی که ممکن است برگرداند و ... که باید به درستی توضیح داده شوند.

توضیح اشیاء و متدها و ... شامل مواردی چون: هدف از ایجاد آن، آرگومان هایی که به آن پاس می‌شوند و خروجی که می‌دهد و اینکه قالب یا فرمت آن‌ها چگونه است و چه محدودیت‌هایی در مقادیر قابل انتظار وجود دارند. ذکر محدودیت‌ها، مورد بسیاری مهمی است و دلیل بسیاری از باگ‌ها، عدم توجه یا اطلاع نداشتن از وجود این محدودیت هاست. مثلا محدوده‌ی خاصی برای آرگومان‌های ورودی وجود دارد؟ چه اتفاقی می‌افتد اگر به یک بافر 128 کاراکتری، 1024 کاراکتر را ارسال کنیم؟

کدهای منطقی عجیب، یکی از حیاتی‌ترین بخش‌های کامنت گذاری برای نگه داری یک برنامه در آینده است. به عنوان نمونه استفاده از عبارات با قاعده، اغلب اوقات باعث سردرگمی کاربران شده است. پس توضیح دادن در مورد این نوع کدها، توصیه زیادی می‌شود. اگر عبارات با قاعده شما طولانی هستند، سعی کنید از هم جدایشان کنید یا خطوط آن را بشکنید و هر خط آن را توضیح دهید.

سیستم کامنت گذاری
هر زبانی از یک سیستم خاص برای کامنت گذاری استفاده می‌کند. به عنوان مثال پرل از سیستم (POD (Plain Old Documentation استفاده می‌کند یا برای Java سیستم JavaDoc یا برای PHP از سیستم PHPDoc  (+ ) که پیاده سازی از JavaDoc می‌باشد استفاده می‌کنند. این سیستم برای سی شارپ استفاده از قالب XML است. کد زیر نمونه‌ای از استفاده از این سیستم است:
// XMLsample.cs
// compile with: /doc:XMLsample.xml
using System;
/// <summary>
/// Class level summary documentation goes here.</summary>
/// <remarks>
/// Longer comments can be associated with a type or member
/// through the remarks tag</remarks>
public class SomeClass
{
    /// <summary>
    /// Store for the name property</summary>
    private string myName = null;

    /// <summary>
    /// The class constructor. </summary>
    public SomeClass()
    {
        // TODO: Add Constructor Logic here
    }

    /// <summary>
    /// Name property </summary>
    /// <value>
    /// A value tag is used to describe the property value</value>
    public string Name
    {
        get
        {
            if (myName == null)
            {
                throw new Exception("Name is null");
            }
            return myName;
        }
    }

    /// <summary>
    /// Description for SomeMethod.</summary>
    /// <param name="s"> Parameter description for s goes here</param>
    /// <seealso cref="String">
    /// You can use the cref attribute on any tag to reference a type or member
    /// and the compiler will check that the reference exists. </seealso>
    public void SomeMethod(string s)
    {
    }
}

دستورات سیستم کامنت گذاری سی شارپ

در سایت جاری، دو مقاله زیر اطلاعاتی در رابطه با نحوه‌ی کامنت گذاری ارئه داده‌اند.
- در مقاله «زیباتر کد بنویسیم» چند مورد آن به این موضوع اختصاص دارد.
- مقاله «وادار کردن خود به کامنت نوشتن» گزینه‌ی کامنت گذاری اجباری در ویژوال استودیو را معرفی می‌کند.
نظرات اشتراک‌ها
فریم ورک Material UI
با سلام ... 
میخواستم بدونم این فریمورک رایگان هست یا تجاری و پولی؟
و اینکه برای یادگیریش منبع فارسی هست ؟ اگر نیست انگلیسی چطور ؟ من خیلی علاقه مند به یادگیری این فریمورک هستم
با تشکر
مطالب
Closure در JavaScript
در قسمت قبلی درباره علت نیاز به الگوهای طراحی در JavaScript و Function Spaghetti code صحبت شد. در این قسمت Closure در JavaScript مورد بررسی قرار می‌گیرد. 
در JavaScript می‌توان توابع تو در تو نوشت (nested functions) ، زمانی که یک تابع درون تابع دیگر تعریف می‌شود تابع درونی به تمام متغیر‌ها و توابع تابع بیرونی (Parent) دسترسی دارد.
Douglas Crockford برای تعریف Closure می‌گوید : 

an inner function always has access to the vars and parameters of its outer function, even after the outer  function has returned

یک تابع درونی (nested) همیشه به متغیر‌ها و پارامتر‌ها تابع بیرونی دسترسی دارد ، حتی اگر تابع بیرونی مقدار برگردانده باشد. 

تابع زیر را در نظر بگیرید : 
// The getDate() function returns a nested function which refers the 'date' variable defined
// by outer function getDate()
function getDate() {
   var date = new Date();    // This variable stays around even after function returns

   // nested function
   return function () {
      return date.getMilliseconds();
   }
}

  اکنون اگر به صورت زیر تابع getDate فراخوانی شود مشاهده می‌شود که تابع درونی (با کامنت nested function مشخص شده است.) به شیء date دسترسی دارد.
// Once getDate() is executed the variable date should be out of scope and it is, but since
// the inner function
// referenes date, this value is available to the inner function.
var dt = getDate();

alert(dt());
alert(dt());
خروجی هر 2 alert یک مقدار خواهد بود. 
اگر از فردی که به تازگی رو به JavaScript آورده است خواسته شود تابعی بنویسد که میلی ثانیه‌ی زمان جاری را برگداند احتمالا همچین کدی تحویل می‌دهد : 
        function myNonClosure() {
            var date = new Date();
            return date.getMilliseconds();
        }
در کد بالا پس از اجرای myNonClosure متغیر date از بین خواهد رفت ، این مسئله در دنیای JavaScript طبیعی هست.
این مثال را در نظر بگیرید :  
var MyDate = function () {
    var date = new Date();
    var getMilliSeconds = function () {
        return date.getMilliseconds();
    }
}

var dt = new MyDate();

alert(dt.getMilliSeconds());  // This will throw error as getMilliSeconds is not accessible.
در صورت اجرای مثال بالا خطایی با این مضمون دریافت خواهد شد که getMilliSeconds دستیابی پذیر نیست. (کپسوله شده)  برای اینکه آن را دستیابی پذیر کنیم کد را به این صورت تغییر می‌دهیم :
// This is closure 
var MyDate = function () {
    var date = new Date();   // variable stays around even after function returns
    var getMilliSeconds = function () {
        return date.getMilliseconds();
    };
    return {
        getMs : getMilliSeconds
    }
}
آنچه در تابع بالا انجام شده کپسوله سازی همه‌ی منطق کار (منطق کار در اینجا برگرداندن میلی ثانیه زمان جاری می‌باشد) در یک فضای نام به نام MyDate می‌باشد. همچنین فقط متد‌های عمومی در اختیار استفاده کننده این تابع قرار داده شده است. برای استفاده می‌توان بدین صورت عمل کرد : 
var dt = new MyDate();
alert(dt.getMs());  // This should work.
در کد بالا برای توابع و متغیر‌های درونی یک container ایجاد کردیم که باعث جلوگیری از تداخل در نام متغیر‌ها با دیگر کد‌ها خواهد شد . (برای مشاهده‌ی تداخل‌ها به قسمت قبلی  توجه کنید.)
اگر بخواهیم Closure را تشبیه کنیم ، Closure شبیه به کلاس‌ها در C# یا Java هست. 
Closure یک حوزه (scope) برای متغیر‌ها و توابع درونی خودش ایجاد می‌کند.
jQuery بهترین مثال کاربردی برای Closure می‌باشد : 
(function($) {

    // $() is available here

})(jQuery);
در ادامه این مفاهیم بیشتر توضیح داده می‌شودند ، اکنون می‌خواهیم مشکلی که در قسمت قبلی مطرح کردیم به کمک Closure حل کنیم : 
 در آن مثال گفته شد که اگر : 
// file1.js
function saveState(obj) {
    // write code here to saveState of some object
    alert('file1 saveState');
}
// file2.js (remote team or some third party scripts)
function saveState(obj, obj2) {
     // further code...
    alert('file2 saveState");
}
اگر تابعی به نام saveState در 2 فایل مختلف داشته باشیم و این 2 فایل را بدین صورت در برنامه آدرس دهیم : 
<script src="file1.js" type="text/javascript"></script>
<script src="file2.js" type="text/javascript"></script>
تابع saveState در فایل دوم تابع saveState فایل اول را override می‌کند. یک از توابع بالا را به صورت زیر باز نویسی می‌کنیم و منطق کار را کپسوله می‌کنیم : 
function App() {
    var save = function (o) {
        // write code to save state here..
        // you have acces to 'o' here...
        alert(o);
    };

    return {
        saveState: save
    };
}
بدون نگرانی تداخل saveState با بقیه saveState‌ها در هر پلاگین یا فایل دیگری می‌توان از saveState می‌توان اینگونه استفاده کرد : 
var app = new App();

app.saveState({ name: "rajesh"});
برای اطلاعات بیشتر در مورد Closure ها این لینک  را بررسی کنید.
اشتراک‌ها
مفهوم Loose Coupling

Anyone can write software, but it takes a seasoned developer to write decoupled software. Today, I cover the definition of loose coupling, how to detect it, and ways to improve your code. 

مفهوم Loose Coupling
اشتراک‌ها
تست جوئل برای برنامه نویس‌ها

The Joel Test is great for software development shops and for programmers that are interested in quickly evaluating a company’s software development environment, but what about a Joel Test for actual programmers? 

تست جوئل برای برنامه نویس‌ها
اشتراک‌ها
سری آموزشی Automated Software Testing

Automated Software Testing Series - Visual Studio Toolbox
12 videos
Welcome to the 12-part series on automated software testing, where you will learn how to increase the efficiency and ROI of your software testing. We cover unit testing, behavior style testing, mocking, integration testing and more. 

سری آموزشی Automated Software Testing
مطالب
بررسی بارگذاری داده ها در انبار های داده و معرفی الگوهای بکار رفته در آن

مقدمه

در لینکی که چندی پیش به اشتراک گذاشته بودم؛ به مطلبی تحت این عنوان اشاره شده بود: "آیا از KPI باید به انباره داده و هوش تجاری رسید؟" (بر گرفته از وبلاگ آقای جام سحر) که در آن به موانع پیش روی انجام پروژه‌های BI در ایران پرداخته شده است.
این مقاله بر گرفته از فصل سوم یکی از White Paper‌های ماکروسافت با عنوان Microsoft EDW Architecture, Guidance and Deployment Best Practices می‌باشد. که به شرح عملیات Loading در فاز ETL می‌پردازد. از آنجا که به منظور پیاده سازی این نوع پروژه‌ها معمولاً در ایران برون سپاری صورت می‌گیرد و مدیران شرکت‌ها بیشتر درگیر سیستم‌های OLTP هستند و مجری پروژه (شرکت پیمانکار) معمولاً کوتاهترین مسیر را جهت انجام پروژه انتخاب می‌کند(و امروزه نیک میدانیم که "انتخاب مسیرهای کوتاه در زمان کم می‌تواند به پیچیدگی‌های بسیار جدی در دراز مدت منجر شود!") و همچنین از آنجا که متاسفانه به دلیل عدم ثبات مدیریت در ایران معمولاً "مدیریت برای تحویل پروژه تحت فشار است و نه برای مسائل پشتیبانی " و مسائل دیگری از این دست؛ چنانچه در تحویل گیری محصول به درستی تست نرم افزار صورت نگیرد، در نظر گرفتن موارد زیر:
Verification: Are we building the product right? ~ Software correctly implements a specific function
  Validation: Are we building the right product? ~  Software is traceable to customer requirements
پروژه با شکست مواجه می‌شود و انتظارات مدیران بهره بردار را برآورده نمی‌کند. به هر روی در این مقاله به ترجمه مطالب زیر پرداخته می‌شود، توصیه میکنم در صورتی که با خواندن متن انگلیسی مشکلی ندارید، اصل مقاله مذکور خوانده شود.
1- Full Load vs Incremental Load
2- Detecting Net Changes
2-1- Pulling Net Changes – Last Change Column
2-2- Pulling Net Changes – No Last Change Column
2-3- Pushing Net Changes
3- ETL Patterns
3-1- Destination load Patterns
3-2- Versioned Insert Pattern
3-3- Update Pattern
3-4- Versioned Insert: Net Changes 
4- Data Integration Best Practices
4-1- Basic Data Flow Patterns
4-1-1- Update Pattern
4-1-2- Update Pattern – ETL Framework
4-1-3- Versioned Insert Pattern
4-1-4- Update vs. Versioned Insert
4-2- Dimension Patterns
4-3- Fact Table Patterns
4-3-1- Managing Inferred Members

1- Full Load vs Incremental Load

نسل‌های اولیه DW (اختصار Data Warehouse) به شکل Full Loads پیاده سازی می‌شدند، به این طریق که هر بار عملیات بارگذاری صورت می‌گرفت، DW از نو دوباره ساخته می‌شد. شکل زیر مراحل مختلف انجام شده در این روش را نمایش می‌دهد:

پروسه Full Load شامل مراحل زیر بود:

  1. Drop Indexes: از آنجا که Index‌ها زمان بارگذاری را افزایش می‌دادند، این عمل صورت می‌پذیرفت.
  2. Truncate Tables: تمامی رکوردهای موجود در جداول حذف می‌شدند.
  3. Bulk Copy
  4. Load Data
  5. Post Process: شامل عملیاتی نظیر شاخص گذاری روی داده هایی است که اخیراً بارگذاری شده اند و....

روی  هم رفته Full Load مسئله ای مشکل ساز بود، زیرا نیاز به زمانی برای بارگذاری مجدد داده‌ها داشت و مسئله‌ی مهم‌تر نداشتن امکان دستیابی به گزارشاتی تاریخچه ای با ماهیت زمان برای مشتریان کسب وکار بود. به این دلیل که همواره یک کپی از آخرین داده‌های موجود در سیستم عملیاتی درون DW قرار می‌گرفت؛ که با بکارگیری Full Load اغلب قادر به ارائه‌ی این نوع از گزارشات نبودیم، بدین ترتیب سازمان‌ها به نسل دوم روی آورند که در این دیدگاه از مفهوم Incremental Load استفاده می‌شود. اشکال زیر مراحلی که در این روش انجام می‌شود را نمایان می‌سازد:

Incremental Load with an Extract In area

Incremental Load without an Extract In area

مراحل Incremental Load شامل:

  1. بارگذاری تغییرات نسبت به آخرین فرآیند بارگذاری انجام شده
  2. درج / بروزرسانی تغییرات درون Production area
  3. درج / بروزرسانی Consumption area نسبت به Production area


تفاوت‌های اصلی میان Full Load و Incremental Load در این است که در Incremental Load:

  • نیازی به پردازش‌های اضافی جهت حذف شاخص ها، پاک کردن تمامی رکورد‌های جداول و ساخت مجدد شاخص‌ها نیست.
  • البته نیاز به رویه ای جهت شناسایی تغییرات می‌باشد.
  • و همچنین نیاز به بروزرسانی  بعلاوه درج رکوردهای جدید نیز می‌باشد.

ترکیب این عوامل برای ساخت Incremental Load کارآمد تر، منجر به پیچیده‌تر شدن پیاده سازی و نگهداری آن نیز می‌شود.

2- Detecting Net Changes

فرآیند لود افزایشی ETL، بایست قادر به شناسائی رکورد‌های تغییریافته در مبداء باشد، که این عمل با استفاده از هر یک از تکنیک‌های Push یا Pull انجام می‌شود.

  • در تکنیک Pull، فرآیند ETL رکوردهای تغییریافته در مبداء را انتخاب می‌کند:
  • ایده‌آل وجود داشتن یک ستون Last Changed در سیستم مبداء است؛ که از آن می‌توان جهت انتخاب رکوردهای تغییر یافته استفاده نمود.
  • چنانچه ستون Last Changed وجود نداشته باشد، تمامی رکوردهای مبداء باید با رکورد‌های مقصد مقایسه شود.
  • در تکنیک Push، مبداء تغییرات را شناسائی می‌کند و آنها را به سمت مقصد Push می‌کند؛ این درخواست می‌تواند توسط فرآیند ETL انجام شود.
از آنجایی که پردازش ETL معمولاً در زمان هایی که Peak کاری وجود ندارد، اجرا می‌شود، استفاده از مکانیسم Pull برای شناسایی تغییرات نسبت به مکانسیم Push ارجحیت دارد.


2-1- Pulling Net Changes – Last Change Column

بیشتر جداول در سیستم‌های مبداء حاوی ستون هایی هستند که زمان ایجاد و یا اصلاح رکوردها را ثبت می‌کنند. در نوع دیگری از سیستم‌های مبداء ستونی با مقدار عددی وجود دارد، که هر زمان رکوردی تغییر یافت به آن ستون مقداری اضافه می‌شود. هر دوی این تکنیک‌ها به فرآیند ETL اجازه می‌دهند، بطور کارآمدی رکوردهای تغییریافته را انتخاب کند. (با مقایسه، بیشترین مقدار قرار گرفته در آن ستون؛ که در طول آخرین اجرای فرآیند ETL بدست آمده است). نمونه ای از جداول سیستم مبداء که دارای تغییرات زمانی است در شکل زیر نمایش داده می‌شود.

همچنین شکل زیر نشان می‌دهد، چگونه یک مقدار عددی می‌تواند به منظور انتخاب رکوردهای تغییریافته استفاده شود.

2-2- Pulling Net Changes – No Last Change Column

شکل زیر گردش فرآیند را هنگامی که ستون Last Change وجود ندارد؛ نمایش می‌دهد.


این گردش فرآیند شامل:
  1. Join میان مبداء و مقصد با استفاده از یک دستور Left Outer Join است.
  2. تمامی رکورد‌های مبداء که در مقصد وجود ندارند، پردازش می‌شوند.
  3. زمانی که رکوردی در مقصد وجود داشته باشد مقادیر داده‌های مبداء و مقصد مقایسه می‌شوند.
  4. تمامی رکوردهای مبداء که تغییر یافته اند پردازش می‌شوند.
از آنجایی که تمامی رکورد‌ها پردازش می‌شوند، این روش بویژه برای جداول حجیم؛ روش کارآمدی نیست.

2-3- Pushing Net Changes

دو متد متداول Push وجود دارد که در تصویر زیر نمایش داده  شده است.

تفاوت این دو روش به شرح زیر است:

  1. در سناریو اول (شکل سمت چپ)؛ بانک اطلاعاتی رابطه ای سیستم مبداء Transaction Log را مرتب مانیتور می‌کند تا تغییرات را شناسائی کرده و در ادامه تمامی این تغییرات را در جدولی در مقصد درج می‌کند.
  2. در سناریو دوم؛ توسعه دهندگان Trigger هایی ایجاد می‌کنند تا هر زمان که رکوردی تغییر یافت، تغییرات در جدولی که در مقصد وجود دارد درج گردد.

مسئله ای که در هر دو مورد وجود دارد Load اضافه ای است؛ که روی سیستم مبداء وجود دارد و می‌تواند Performance سیستم‌های OLTP را تحت تاثیر قرار دهد. به هر روی سناریو نخست معمولاً کاراتر از سناریویی است که از Trigger استفاده می‌کند.

3- ETL Patterns

پس از شناسائی رکوردهایی که در مبداء تغییر یافته اند، نیاز داریم تا این تغییرات در مقصد اعمال شود. در این قسمت به معرفی الگوهایی که برای اعمال این تغییرات وجود دارد می‌پردازیم.

3-1- Destination load Patterns

تشخیص چگونگی اضافه نمودن تغییرات در مقصد تابع دو عامل زیر است:

  • آیا رکورد هم اینک در مقصد وجود دارد؟
  • الگوی استفاده شده برای جدول مقصد به کدام شکل است؟ (Update یا Versioned Insert)

فلوچارت زیر نشان می‌دهد، به چه شکل جداول مقصد متاثر از چگونگی پردازش رکوردهای مبداء قرار دارند. توجه داشته باشید که عمل بررسی بطور جداگانه و در یک لحظه صورت می‌گیرد.
 

3-2- Versioned Insert Pattern

Kimball Type II Slowly Changing Dimension نمونه ای از الگوی Versioned Insert است؛ که در آن نمونه ای از یک موجودیت دارای ورژن‌های متعددی است. مطابق تصویر زیر؛ این الگو به ستون‌های اضافه ای نیاز دارند که وضعیت نمونه ای از یک رکورد را نمایش دهد.


این ستون‌ها به شرح زیر هستند:

  • Start Date: زمانی که وضعیت آن نمونه از رکورد فعال می‌شود.
  • End Date: زمانی که وضعیت آن نمونه از رکورد غیر فعال می‌شود.
  • Record Status: وضعیت‌های یک رکورد را نشان می‌دهد، که حداقل به شکل Active یا Inactive است.
  • # Version: این ستون که اختیاری می‌باشد، ورژن آن نمونه از رکورد را ثبت می‌کند.


برای مثال شکل زیر؛ بیانگر وضعیت اولیه رکوردی در این الگو است:


فرض کنید که این رکورد در تاریخ March 2 , 2010 در سیستم مبداء تغییر می‌کند. فرآیند ETL این تغییر را شناسائی می‌کند و همانند تصویر زیر؛ به شکل نمونه ای ثانویه از این رکورد، اقدام به درج آن می‌کند.

توجه داشته باشید زمانی که رکورد دوم در جدول درج می‌شود، به منظور بازتاب این تغییر؛ رکورد اول به شکل زیر بروزرسانی می‌گردد:

  • End Date: تا این زمان وضعیت این رکورد فعال بوده است.
  • Record Status:که Active به Inactive تغییر پیدا می‌کند.


در برخی از پیاده سازی‌های DW عمدتاً از الگوی Versioned Insert استفاده می‌شود و هرگز از الگوی Update استفاده نمی‌شود. مزیت این استراتژی در این است که تمامی تاریخچه تغییرات ردیابی و ثبت می‌شود. به هر روی غالباً هزینه ثبت کردن این تغییرات منجر به ایجاد نسخه‌های زیادی از تغییرات می‌شود. تیم DW برای مواردی که تغییرات متاثر از گزارشات تاریخچه ای نیستند، می‌توانند الگوی Update را در نظر گیرند.

3-3- Update Pattern

الگوی Update روی رکورد موجود، تغییرات سیستم مبداء را بروزرسانی می‌کند. مزیت این روش در این است که همواره یک رکورد وجود دارد و در نتیجه باعث ایجاد Query‌های کارآمدتر می‌شود. تصویر زیر بیانگر ستون هایی است که برای پشتیبانی از الگوی Update بایست ایجاد کرد.


این ستون‌ها به شرح زیر هستند:

  • Record Status: وضعیت‌های یک رکورد را نشان می‌دهد که حداقل به شکل Active یا Inactive است.
  • # Version: این ستون که اختیاری می‌باشد، ورژن آن نمونه از رکورد را ثبت می‌کند.


موارد اصلی الگوی Update عبارتند از:

  • تاریخ ثبت نمی‌شود. ابزاری ارزشمند برای نظارت بر داده ها، تغییرات تاریخی است و زمانی که ممیزی داده رخ می‌دهد؛ می‌تواند مفید واقع شود.
  • بروزرسانی‌ها یک الگوی مبتنی بر مجموعه هستند. استفاده از بروزرسانی هر بار یک رکورد در ابزار ETL خیلی کارآمد (موجه) نیست.


یک روش دیگر برای در نظر گرفتن موارد فوق؛ اضافه کردن یک جدول برای درج ورژن‌ها به الگوی Update است که در شکل زیر نشان داده شده است.


اضافه نمودن یک جدول تاریخچه، که تمامی تغییرات سیستم مبداء را ثبت  می‌کند؛ نظارت و ممیزی داده‌ها را نیز فراهم می‌کند و همچنین بروزرسانی‌های کارآمد مبتنی بر مجموعه را برای جداول DW به ارمغان می‌آورد.

3-4- Versioned Insert: Net Changes 

این الگو غالباً در جداول حجیم Fact که بروزرسانی آنها پر هزینه است استفاده می‌شود. شکل زیر منطق استفاده شده در این الگو را نشان می‌دهد.

توجه داشته باشید در این الگو:
  • مقادیر مالی و عددی محاسبه شده؛ به عنوان یک Net Change از نمونه قبلی رکورد در جدول Fact ذخیره می‌شود.
  • هیچ گونه فعالیت Post Processing صورت نمی‌گیرد (از قبیل بروزرسانی جداول Fact پس از کامل شدن Data Flow). هدف استفاده از این الگو اجتناب از بروزرسانی روی جداول بسیار حجیم می‌باشد.
  • عدم بروزرسانی و همچنین اندازه جدول Fact زمینه ای را فراهم می‌کند که منطق شناسائی رکوردهای تغییریافته پیچیده تر  می‌شود. این پیچیدگی از آنجا ناشی می‌شود که نیاز به مقایسه رکوردهای جدول Fact آتی با جدول Fact موجود می‌باشد.

4- Data Integration Best Practices

هم اکنون پس از آشنایی با مفاهیم و الگو‌های توزیع داده‌ها به ارائه تعدادی نمونه می‌پردازیم؛ که بتوان این ایده‌ها و الگوها را در عمل پوشش داد.

4-1- Basic Data Flow Patterns

هر یک از الگوهای Update Pattern و Versioned Insert Pattern می‌توانند برای انواعی از جداول بکار روند که معروفترین آن‌ها توسط Kimball ساخته شده اند.

  • (Slowly Changing Dimension Type I (SCD I: از Update Pattern استفاده می‌کند.
  • (Slowly Changing Dimension Type II (SCD II: از Versioned Insert Pattern استفاده می‌کند.
  • Fact Table: نوع الگویی که استفاده می‌کند به نوع جدول Fact ای که Load خواهد شد بستگی دارد.

4-1-1- Update Pattern 

مطابق تصویر زیر جدولی که تنها حاوی ورژن فعلی رکورد هاست؛ از Update Dataflow Pattern استفاده می‌کند.


مواردی که در مورد این گردش کاری باید در نظر داشت به شرح زیر است:

  • این Data Flow فقط سطرهایی را به یک مقصد اضافه خواهد کرد. SSIS دارای گزینه “Table or view fast load” می‌باشد که بارگذاری‌های انبوه و سریع را پشتیبانی می‌کند.
  • درون یک Data Flow بروزرسانی  رکورد‌ها را می‌توان با استفاده از تبدیل OLE DB Command انجام داد. توجه داشته باشید خروجی‌های این تبدیل در یک دستور Update به ازای هر رکورد بکار می‌رود؛ مفهوم بروزرسانی انبوه در این Data Flow وجود ندارد. بدین ترتیب الگوی فعلی ارائه شده؛ تنها رکوردها را درج می‌کند و هرگز در این Data Flow رکوردها Update نمی‌شوند.
  • هر جدول دارای یک جدول تاریخچه است که برای ذخیره همه فعالیت‌های مرتبط با آن بکار می‌رود. یک رکورد در جدول تاریخچه زمانی درج خواهد شد؛ که رکورد مبداء در مقصد وجود داشته باشد ولی دارای مقداری متفاوت باشد.
  • راه دیگر فرستادن تغییرات رکوردها به یک جدول کاری است که پس از پایان یافتن فرآیند Update ، خالی (Truncate) می‌شود.
  • مزیت نگهداری تمامی رکوردها در یک جدول تاریخچه؛ ایجاد یک دنباله ممیزی است که می‌تواند برای نظارت بر داده‌ها به منظور نمایان ساختن موارد مطرح شده توسط مصرف کننده‌های کسب و کار استفاده شود.
  • گزینه‌های متفاوتی برای تشخیص تغییرات رکوردها وجود دارد که در ادامه به شرح آنها می‌پردازیم.


شکل زیر نمایش دهنده چگونگی پیاده سازی Update Dataflow Pattern در یک SSIS می‌باشد:


این SSIS شامل عناصر زیر است:

  • Destination table lookup:

به منظور تشخیص اینکه رکورد در جدول مقصد وجود دارد از “lkpPersonContact” استفاده می‌کنیم.

  • Change detection logic:

با استفاده از “DidRecordChange” مبداء و مقصد مقایسه می‌شوند. اگر تفاوتی بین مبداء و مقصد وجود نداشت؛ رکورد نادیده گرفته می‌شود. چنانچه بین مبداء و مقصد تفاوت وجود داشت؛ رکورد در جدول تاریخچه درج خواهد شد.

  • Detection Inserts:

رکوردها در جدول مقصد درج خواهند شد در صورتیکه در آن وجود نداشته باشند.

  • Destination History Inserts:

رکوردها در جدول تاریخچه مقصد درج خواهند شد، در صورتیکه (در مقصد) وجود داشته باشند.

پس از اتمام Data Flow یک روال Post-processing مسئولیت بروزرسانی رکوردهای جدول اصلی و رکوردهای ذخیره شده در جدول تاریخچه را بر عهده دارد که می‌تواند مطابق تصویر زیر با استفاده از یک Execute Process Task پیاده سازی شود.


PostProcess مسئولیت اجرای تمامی فعالیت‌های زیر را در این الگو برعهده دارد که شامل:

  • بروزرسانی رکوردهای جداول با استفاده از رکوردهای درج شده در جدول تاریخچه.
  • درج تمامی رکوردهای جدید (نسخه اولیه و در درون جدول تاریخچه). کلید اصلی جداولی که ستون  آنها IDENTITY است مقدار نامشخصی دارد؛ تا زمانی که درج صورت گیرد، این به معنای آن است که پیش از انتقال آنها به جدول تاریخچه نیاز است منتظر درج شدن آنها باشیم.

4-1-2- Update Pattern – ETL Framework

تصویر زیر بیانگر انجام این عملیات با استفاده از ابزارهای ETL است.
در نگاه نخستین ممکن است Data Flow از نوع اصلی خود پیچیده‌تر به نظر آید؛ که در واقع این گونه نیز هست، زیرا در فاز توسعه بیشتر Framework‌ها جهت پیاده سازی به یک زمان اضافه‌تری نیاز دارند. به هر روی این زمان جهت اجتناب از هزینه روزانه تطبیق داده‌ها گرفته خواهد شد.
مزایای حاصل شده از افزودن این منطق اضافی عبارت است از:

  • پشتیبانی از ستون هایی که کارهای ممیزی و نظارت بر داده‌ها را آسانتر می‌کنند.
  • تعداد سطرها شاخص مناسبی است که می‌تواند بهبود آن Data Flow خاص را فراهم کند. ناظر اطلاعات با استفاده از تعداد رکوردها می‌تواند ناهنجاری‌ها را شناسائی کند.

بهره برداران ETL و ناظران اطلاعات می‌توانند با استفاده از خلاصه تعداد رکوردها درک بیشتری درباره فعالیت‌های آن کسب کنند. پس از آنکه تعداد رکوردها، مشکوک به نظر آمد؛ تحقیقات بیشتری می‌تواند اتفاق افتد. (با عمیق‌تر شدن در جزئیات گزارشات)
 

4-1-3- Versioned Insert Pattern

جدولی که به صورت Versioned Insert پر شده است می‌تواند از Versioned Insert Dataflow Pattern استفاده کند. همانند شکل زیر که گردش کار در آن برای کارآئی بیشتر بازنگری شده است.


توجه داشته باشید Data Flow در این روش شامل:

  • تمامی رکوردهای جدید و تغییر یافته در جدول Versioned Insert قرار می‌گیرند.
  • این روش دارای Data Flow ساده‌تری نسبت به الگوی Update می‌باشد.

شکل زیر SSIS versioned insert data flow pattern را نشان می‌دهد:
 

تعدادی نکته در Data Flow فوق وجود دارد که عبارتند از:

  • در شیء “lkpDimGeography” گزینه “Redirect rows to no match output” با مقدار “Ignore Failures” تنظیم شده است.
  • شیء “DidRecordChange” بررسی می‌کند چنانچه ستون‌های مبداء و مقصد یکسان باشند، آیا کلید اصلی جدول مقصد Not Null است. اگر این عبارت True ارزیابی شود، رکورد نادیده گرفته می‌شود.
  • منطق شناسائی تغییرات دربردارنده تغییرات ستون داده ای در مبداء نمی‌باشد.
  • ستون و تعداد رکوردها مشابه با Data Flow قبلی (ETL Framework) می‌باشد.

4-1-4- Update vs. Versioned Insert

الگوی Versioned Insert نسبت الگوی Update دارای پیاده سازی ساده‌تر و فعالیت‌های I/O کمتری است. از منظر دیگر، جدولی که از الگوی Update استفاده می‌کند، دارای تعداد رکوردهای کمتری است که می‌تواند به معنای Performance بهتر نیز تعبیر شود. ممکن است سوالی مطرح شود، اینکه چرا برای انجام کار به جدول تاریخچه نیاز است؛ این جدول را که نمی‌توان Truncate نمود، پس چرا به منظور بروزرسانی از جدول اصلی استفاده می‌شود؟ پاسخ این پرسش در این است که جدول تاریخچه، ناظر اطلاعات و ممیزین داده را قادر می‌سازد، تغییرات در طول زمان را پیگیری نمایند.
 

4-2- Dimension Patterns

بروزرسانی Dimension موارد زیر را شامل می‌شود:

  • پیگیری تاریخچه
  • انجام بروزرسانی
  • تشخیص رکوردهای جدید
  • مدیریت surrogate keys

چنانچه با یک Dimension کوچک مواجه هستید (با مقدار هزاران رکورد یا کمتر، که با صدها هزار رکورد یا بیشتر ضدیت دارد)،  می‌توانید از تبدیل “Slowly Changing Dimension” که بصورت Built-in در SSIS موجود است، استفاده نمائید. به هر روی با آنکه این تبدیل چندین ویژگی محدودکننده Performance دارد، اغلب کارآمدتر از پروسسه هایی که توسط خودتان ایجاد می‌شود. در واقع فرآیند بارگذاری در جداول Dimension با مقایسه داده‌ها بین مبداء و مقصد انجام می‌شود. به طور معمول مقایسه روی یک ورژن جدید و یا مجموعه ای از سطرهای جدید یک جدول با مجموعه داده‌های موجود در جدول متناظرش صورت می‌گیرد. پس از تشخیص چگونگی تغییر در داده ها، یک سری عملیات درج و بروزرسانی انجام می‌شود. شکل زیر نمونه ای از پردازش سریع در Dimension را نمایش می‌دهد؛ که شامل مراحل اساسی زیر است:

  • منبع فوقانی سمت چپ، رکوردها را در یک SSIS از یک سیستم مبداء (یا یک سیستم میانی) به شکل Pull دریافت می‌کند. منبع فوقانی سمت راست، داده‌ها را از خود جدول Dimension به شکل Pull دریافت می‌کند.
  • با استفاده از Merge Join رکوردها از طریق Source Key شان مقایسه می‌شوند. (در شکل بعدی جزئیات این مقایسه نمایش داده شده است.)
  • با استفاده از یک Conditional Spilt داده‌ها ارزیابی می‌شوند؛ سطرها یا مستقیماً در جدول Dimension درج می‌شوند (منبع تحتانی سمت چپ) و یا در یک جدول عملیاتی (منبع تحتانی سمت راست) جهت انجام بروزرسانی درج می‌شوند.
  • در گام پایانی (که نمایش داده نشده) مجموعه ای از بروزرسانی بین جدول عملیاتی و جدول Dimension صورت می‌گیرد.

 

با Merge Join ارتباطی بین رکوردهای مبداء و رکوردهای مقصد برقرار می‌شود. (در این مثال “CustomerAlternateKey”). هنگامی که از این دیدگاه استفاده می‌کنید، خاطر جمع شوید که نوع Join با مقدار “Left outer join” تنظیم شده است؛ بدین ترتیب قادر هستید تا رکوردهای جدید را از مبداء تشخیص دهید؛ از آنجا که هنوز در جدول Dimension قرار نگرفته اند.


گام پایانی به منظور تشخیص اینکه آیا رکورد، جدید یا تغییر یافته است (یا بلاتکلیف است)، مقایسه داده هاست. شکل زیر نمایش می‌دهد چگونه این ارزیابی با استفاده از تبدیل “Conditional Spilt” صورت می‌گیرد.


Conditional Spilt مستقیماً با استفاده از یک Adapter تعریف شده روی مقصد یا یک جدول کاری بروزرسانی که از یک Adapter تعریف شده روی مقصد استفاده می‌کند؛ توسط مجموعه دستور Update زیر، رکوردها را در جدول Dimension قرار می‌دهد. دستور Update زیر مستقیماً با استفاده از روش Join روی جدول Dimension و جدول کاری، مجموعه ای را بصورت انبوه بروزرسانی می‌کند.

UPDATE AdventureWorksDW2008R2.dbo.DimCustomer
    SET AddressLine1 = stgDimCustomerUpdates.AddressLine1
    , AddressLine2 = stgDimCustomerUpdates.AddressLine2
    , BirthDate = stgDimCustomerUpdates.BirthDate
    , CommuteDistance = stgDimCustomerUpdates.CommuteDistance
    , DateFirstPurchase = stgDimCustomerUpdates.DateFirstPurchase
    , EmailAddress = stgDimCustomerUpdates.EmailAddress
    , EnglishEducation = stgDimCustomerUpdates.EnglishEducation
    , EnglishOccupation = stgDimCustomerUpdates.EnglishOccupation
    , FirstName = stgDimCustomerUpdates.FirstName
    , Gender = stgDimCustomerUpdates.Gender
    , GeographyKey = stgDimCustomerUpdates.GeographyKey
    , HouseOwnerFlag = stgDimCustomerUpdates.HouseOwnerFlag
    , LastName = stgDimCustomerUpdates.LastName
    , MaritalStatus = stgDimCustomerUpdates.MaritalStatus
    , MiddleName = stgDimCustomerUpdates.MiddleName
    , NumberCarsOwned = stgDimCustomerUpdates.NumberCarsOwned
    , NumberChildrenAtHome = stgDimCustomerUpdates.NumberChildrenAtHome
    , Phone = stgDimCustomerUpdates.Phone
    , Suffix = stgDimCustomerUpdates.Suffix
    , Title = stgDimCustomerUpdates.Title
    , TotalChildren = stgDimCustomerUpdates.TotalChildren
FROM AdventureWorksDW2008.dbo.DimCustomer DimCustomer
  INNER JOIN dbo.stgDimCustomerUpdates ON
DimCustomer.CustomerAlternateKey = stgDimCustomerUpdates.CustomerAlternateKey

4-3- Fact Table Patterns

جداول Fact به پردازش‌های منحصر به فردی نیازمند هستند، نخست به کلیدهای Surrogate جدول Dimension نیاز دارند تا Measure‌های محاسبه شدنی را بدست آورند. این اعمال از طریق تبدیلات Lookup، Merge Join و Derived Column صورت می‌گیرد. با بروزرسانی ها، تفاضل رکورد‌ها و یا Snapshot بیشتر این فرآیندهای دشوار انجام می‌شوند.

4-3-1- Inserts

روی اغلب جداول Fact عمل درج صورت می‌گیرد؛ که کار متداولی در جدول Fact می‌باشد. شاید ساده‌ترین کار که در فرآیند ساخت ETL صورت می‌گیرد، عملیات درج روی تنها تعدادی از جدول Fact می‌باشد. درج کردن در صورت لزوم بارگذاری انبوه داده ها، مدیریت شاخص‌ها و مدیریت پارتیشن‌ها را شامل می‌شود.

4-3-2- Updates

بروزرسانی روی جداول Fact معمولاً به یکی از سه طریق زیر انجام می‌گیرد:

  • از طریق یک تغییر یا بروزرسانی رکورد
  • از طریق یک دستور Insert خنثی کننده (Via an Insert of a compensating transaction)
  • با استفاده از یک SQL MERGE


در موردی که تغییرات با فرکانس کمی روی جدول Fact صورت می‌گیرد و یا فرآیند بروزرسانی قابل مدیریت است؛ ساده‌ترین روش انجام یک دستور Update روی جدول Fact می‌باشد. نکته  مهمی که هنگام انجام بروزرسانی باید به خاطر داشته باشید، استفاده از روش بروزرسانی مبتنی بر مجموعه است؛ به همان طریق که در قسمت الگوهای Dimension ذکر آن رفت.
در طریقی دیگر (درج compensating) می‌توان اقدام به درج رکورد تغییر یافته نمود، تا ترجیحاً بروزرسانی روی آن صورت گیرد. این استراتژی به سادگی داده‌های جدول Fact میان سیستم مبداء و مقصد را که تغییر یافته اند، به صورت یک رکورد جدید درج خواهد کرد. تصویر زیر مثالی از اجرای موارد فوق را نمایش می‌دهد.
 

در آخرین روش از یک دستور SQL MERGE استفاده می‌شود که در آن با استفاده از ادغام و مقایسه، تمامی داده‌های جدید و تغییر یافته جدول Fact، درج و یا بروزرسانی می‌شوند. نمونه ای از استفاده دستور Merge به شرح زیر است:

MERGE dbo.FactSalesQuota AS T
USING SSIS_PDS.dbo.stgFactSalesQuota AS S
ON T.EmployeeKey = S.EmployeeKey
AND T.DateKey = S.DateKey
WHEN MATCHED AND BY target
THEN INSERT(EmployeeKey, DateKey, CalendarYear, CalendarQuarter, SalesAmountQuota)
VALUES(S.EmployeeKey, S.DateKey, S.CalendarYear, S.CalendarQuarter, S.SalesAmountQuota)
WHEN MATCHED AND T.SalesAmountQuota != S.SalesAmountQuota
THEN UPDATE SET T.SalesAmountQuota = S.SalesAmountQuota
;
اشکال این روش Performance است؛ گرچه این دستور به سادگی عملیات درج و بروزرسانی را انجام می‌دهد ولی به صورت سطر به سطر عملیات انجام می‌شود (در هر زمان یک سطر). در موقعیت هایی که با مقدار زیادی داده مواجه هستید، اغلب بهتر است به صورت انبوه عملیات درج و به صورت مجموعه عملیات بروزرسانی انجام گیرد.

4-3-3- Managing Inferred Members

زمانیکه یک ارجاع در جدول Fact به یک عضو Dimension که هنوز بارگذاری نشده‌است بوجود  آید؛ یک Inferred Member تعبیر می‌شود. به سه طریق می‌توان این Inferred Member‌ها را مدیریت نمود:

  • رکوردهای جدول Fact پیش از درج اسکن شوند؛ ایجاد هر Inferred Member در Dimension و سپس بارگذاری رکوردها در جدول Fact
  • در طول عملیات بارگذاری روی Fact؛ هر رکورد مفقوده شده به یک جدول موقتی ارسال شود، رکوردهای مفقوده شده به Dimension اضافه شود، در ادامه مجدداً آن رکوردهای Fact در جدول Fact بارگذاری شوند.
  • در یک Data Flow زمانی که یک رکورد مفقود شده، بلاتکلیف تعبیر می‌شود؛ آن زمان یک رکورد به Dimension اضافه شود و Surrogate Key بدست آمده را برگردانیم؛ سپس Dimension بارگذاری شود.


شکل زیر این موارد را نمایش می‌دهد: