Showing posts with label CHECKSUM. Show all posts
Showing posts with label CHECKSUM. Show all posts

Thursday, April 30, 2015

Incremental ETL: How to identify changes for fact data when no support from the source

"Data warehouse is a read-only database": this is one of the characteristics of data warehouse and we used to say "History cannot be changed" for supporting this characteristic. Therefore we always try our best not to bring changes into the data warehouse.

This was thoroughly considered and applied with traditional data warehousing because the cost of processing OLAP models was very high. As I see, with modern implementations, this cost has gone down for two reasons; Tabular Model implementations instead of Multi-Dimensional Models and User-Specific Models with Self-Service BI. Therefore, if it is required, changes can be brought into the data warehouse for some extent considering both cost and benefits of it.

However, when we try to bring changes into the data warehouse, one major issue we face is, less support-ability from sources for finding changes in previous transactions that have already been loaded. Some sources maintain a timestamp indicating the changed date or a flag indicating whether the record is modified or not. If there is no such thing with the source, changes cannot be easily identified. In this scenario, one way of identifying changes is, checking and comparing each and every record, each and every coloumn in the fact table and seeing whether they are different. If the dataset is very large and data warehouse is large too, this is not much practical. Therefore either we should stop taking changes once data is loaded to the data warehouse or should take with some agreed rules.

Here is one of the ways I have used. First of all, we need to set an acceptable time period for accepting changes from the source. The agreed period can be 1 week, 1 month or 3 months. However this is based on certain factors such as business logic involved with transactions, complexity and volume. Once agreed, next step is, holding loaded data in the staging environment for the same period. If we have to expect changes for last three months, we need to make sure that staging database has last three months extracted data. In addition to that, we need to maintain an additional column for holding checksum. That is what we have to used for comparing records between the source and staging, not comparing each and every column.

For example, assume that Sales data related to FactSales in SalesDataWarehouse is loaded via a staging table which is called Sales. For that, considering the above requirement, the structure of the staging table must be created as below;

-- Staging table for holding sales
CREATE TABLE dbo.Sales
(
 SalesOrderID int NOT NULL
 , OrderDate datetime NOT NULL
 , ShipDate datetime NOT NULL
 , SalesOrderNumber varchar(25) NOT NULL
 , Product varchar(100) NOT NULL
 , ListPrice money NOT NULL
 , UnitPrice money NOT NULL
 , OrderQty int NOT NULL
 , LineTotal money NOT NULL
 , CheckSumValue int NOT NULL -- Checksum value from above columns
 , RecordType tinyint NOT NULL -- 1-New, 2-Modified, 3-Loaded
);
GO

-- Creating clustered index
CREATE UNIQUE CLUSTERED INDEX IX_Sales_SalesOrderID ON dbo.Sales (SalesOrderID);
GO

-- Creating an index on Checksum column
CREATE INDEX IX_Sales_SalesOrderID ON dbo.Sales (SalesOrderID);
GO

When we load new data, for an example, yesterday data, we load data into the staging table with RecordType = 1. Once inserted, must generate the Checksum value for newly inserted records.

UPDATE dbo.Sales
 SET CheckSumValue = Checksum(SalesOrderID, OrderDate
      , ShipDate, SalesOrderNumber
      , Product, ListPrice, UnitPrice
      , OrderQty, LineTotal)
WHERE RecordType = 1;

After that ETL module can access new records for loading the data warehouse. Once done,  RecordType must be set to 3. Now how do we handle changes for last three months?

For that, we need to get last three months transactions from the source again and calculate the checksum for extracted data. If SSIS is used for loading the staging, then we can load data into a Data Flow and generate the new Checksum. If we use a method like bcp or TSQL, it is better to load them into another temporary table. Once we have the dataset with new checksum, records can be checked and seen by comparing new checksum and old checksum, and update the records in the staging as below;

UPDATE dbo.Sales
 SET OrderDate = t.OrderDate
  , ShipDate = t.ShipDate
  , SalesOrderNumber = t.SalesOrderNumber
  , Product = t.Product
  , ListPrice = t.ListPrice
  , UnitPrice = t.UnitPrice 
  , OrderQty = t.OrderQty
  , LineTotal = t.LineTotal
  , RecordType = 2
FROM dbo.Sales s
 INNER JOIN TempSales t
  ON s.SalesOrderID = t.SalesOrderID 
   AND s.CheckSumValue != Checksum(t.SalesOrderID, t.OrderDate
      , t.ShipDate, t.SalesOrderNumber
      , t.Product, t.ListPrice, t.UnitPrice
      , t.OrderQty, t.LineTotal);

This updates RecordType as 2 indicating that the record is changed. Once updated, another ETL can access these records and update FactSales in the data warehouse.

This reduces the complexity related to finding changes and time and resources required for processing. However, since we use Checksum, for certain situation, same value might generated for the new value even though there is a change. If you experience it, it is recommended to use Hasbytes instead of Checksum.


Sunday, July 18, 2010

SQL Server Page Size – 8KB and Hard Drive Sector Size – 512 bytes???

Discussion related to SQL Server page sizes and OS page sizes was started up while my new SQL Server class was being done. New batch is really good; they ask questions :).

SQL Server maintains data with 8KB data pages. If SQL Server has a table called dbo.Customer, based on the number of records, size of the record, data will be held on hundreds of thousands of 8KB data pages. Although SQL Server maintain 8KB pages, those pages have to be written to the disk, into 512 bytes sectors, which means, 8KB page will be broken into 16 sectors. In other words, data in a database page will be distributed among 16 sectors. SQL Server has no knowledge on the completion of this distribution (by default it assumes that 8KB is written to 16 sectors with no errors once the first sector is written [Correct me if I am wrong]). If something has happened during the write process, we will see errors when data is read back and we might not be able to find the exact problem, or exact IO path. Luckily, there is feature that checks whether those 16 pages are written properly when data is read back from the disk. Explanation of it is given below, but the question raised from my class was related to sector size. Is it 512 bytes???

Sector refers the minimum chunk of data that can be written or read to a hard drive (Read more on Sector: http://en.wikipedia.org/wiki/Disk_sector). K, back to the question, do we still see 512 bytes size sectors? I had no direct answer when the question was raised because my knowledge on hardware is bit poor. So, as usual, googled and found some info.

Here is what I found: It depends, 512 bytes was the standard size for the sector during 1956. Nowadays we get larger size of sectors such as 1KB to 4KB (or more?). In that case, for example, if SQL Server has been installed on a platform that supports 2KB sectors, one database page requires only 4 sectors.

How can we find damaged data pages if something has happened during the write process? It has to be done by PAGE_VERIFY database option. By default it is on and set to CHECKSUM. It can be set either to TORN_PAGE_DETECTION or NONE. CHECKSUM calculates the checksum value for the entire 8KB page and store it in the page header. When the page is read back from the drive, SQL Server calculates it again and matches with the previous stored value. If the value is different, it throws an error message (824). TORN_PAGE_DETECTION creates a specific bit for each sector (512 bytes or 4KB) and stores them in the database page header. These torn bits are checked when pages are read back. Error 824 will be thrown when unmatched torn bits are found. Details of the errors are logged in both SQL Server log and Windows log, allowing us to see the details of error. With most of cases, DBCC CHECKDB helps to resolves the issue.