Presentation is loading. Please wait.

Presentation is loading. Please wait.

Temporal Tables Sam Nasr, MCSA, MVP NIS Technologies July 22, 2017

Similar presentations


Presentation on theme: "Temporal Tables Sam Nasr, MCSA, MVP NIS Technologies July 22, 2017"— Presentation transcript:

1 Temporal Tables Sam Nasr, MCSA, MVP NIS Technologies July 22, 2017

2 Housekeeping Restrooms Forum for learning - Feel free to ask questions
Cell Phones on vibrate please

3 Introduction Software developer since 1995
Sam Nasr Software developer since 1995 Principal Consultant/Instructor (NIS Technologies) MCSA, MCT, MCAD President - Cleveland C#/VB.Net User Group President - .Net Study Group Author for Visual Studio Magazine Microsoft Most Valuable Professional (since 2013)

4 Temporal Tables Temporal Table = System Versioned Table
Based on the ISO/ANSI SQL:2011 standard. New Feature in SQL Server, not all Temporal features supported (i.e. application-time period tables) Maintains current and past states of modified rows Standard feature for all editions of SQL Server 2016 Implement via T-SQL, no additional configuration needed. Application-Time Period Tables: where you can explicitly define the validity period of a row, including in the future.

5 Requirements Primary Key
(2) Period columns (datetime2 type, any name, non-nullable) Start column must include GENERATED ALWAYS AS ROW START End column must include GENERATED ALWAYS AS ROW END Designation: PERIOD FOR SYSTEM_TIME (<startcol>, <endcol>) WITH SYSTEM_VERSIONING = ON HISTORY_TABLE = DepartmentHistory To actually turn on temporal for the table, we add WITH SYSTEM_VERSIONING = ON, and also set the name for the history table that SQL Server should create, and that must include the schema name; although if you leave out the HISTORY_TABLE name, SQL Server will generate one based on the main table’s internal object ID. CREATE TABLE Department ( DepartmentID int NOT NULL IDENTITY(1,1) PRIMARY KEY, DepartmentName varchar(50) NOT NULL, ManagerID int NULL, ValidFrom datetime2 GENERATED ALWAYS AS ROW START NOT NULL, ValidTo datetime2 GENERATED ALWAYS AS ROW END NOT NULL, PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo) ) WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = DepartmentHistory))

6 Querying Temporal Tables
SELECT * FROM Department FOR SYSTEM_TIME AS OF DATEADD(d, -30, SYSDATETIME()) ORDER BY EmployeeId Rows deleted in the past thirty days will be returned Rows created in the past thirty days will NOT be returned. Rows older than thirty days, but modified in the past 30 days are returned as they appeared exactly 30 days ago.

7 Usage Scenarios Allows for querying a table at a specific point-in-time Slowly changing dimensions of a data warehouse Auditing of when the change was made (not who) Recovering from accidental loss of data Anomaly Detection Repairing row-level data corruption Usage Scenarios:

8 Enabling Temporal Existing Tables: New Tables:
Must be done in two separate ALTER TABLE statements. Set DEFAULT values that initialize the period columns with beginning-of-time ( :00: ) until end-of-time ( :59: ) New Tables: CAN create and enable it in a single CREATE TABLE statement Existing table: Must be done in two separate ALTER TABLE statements. Set DEFAULT values that initialize the period columns with beginning-of-time ( :00: ) until end-of-time ( :59: ) New table: CAN create and enable it in a single CREATE TABLE statement

9 Sub clauses

10 Demo Temporal Tables History table appears below the related current table. SSMS identifies the tables as System-Versioned and History in parentheses. Programmatically: OBJECTPROPERTY(TableTemporalType) 1 for a history table 2 for a system versioned table; Default Name Pattern: MSSQL_TemporalHistoryFor_<object_id>.

11 Design Constraints The column type FILESTREAM is not supported, as it stores data outside of the database. For table Foo, the history table will be named “FooHistory” by default. This can be overridden. The history table cannot be modified directly, you can only add to it by updating or deleting data from the current table. INSTEAD OF triggers are not supported and AFTER triggers are only allowed on the current table. Indexing must be manually enabled You cannot change the schema of a Temporal Table.  Convert the Temporal Table into two normal tables using SET (SYSTEM_VERSIONING = OFF) in an ALTER TABLE statement. An optimal indexing strategy will include a clustered columns store index and / or a B-tree rowstore index on the current table and a clustered columnstore index on the history table for optimal storage size and performance. If you create / use your own history table, we strongly recommend that you create such an index that consists of the primary keys from the current table plus the period columns to speed up temporal querying as well as the queries that are part of the data consistency check. If your history table is a rowstore, we recommend a clustered rowstore index. The default history table has a clustered rowstore index created for you. At a minimum, a non-clustered rowstore index is recommended. See

12 Schema Checks Before SYSTEM_VERSIONING = ON …
The names and number of columns is the same in both the current table and the history table. The datatypes match for each column between the current table and the history table. The period columns are set to NOT NULL. The current table has a primary key constraint and the history table does not have a primary key constraint. No IDENTITY columns are defined in the history table. No triggers are defined in the history table. No foreign keys are defined in the history table. No table or column constraints are defined on the history table. However, default column values on the history table are permitted. The history table is not placed in a read-only filegroup. The history table is not configured for change tracking or change data capture. Temporal Table System Consistency Checks Before SYSTEM_VERSIONING is set to ON, a set of checks are performed on the history table and the current table. These checks are grouped into schema checks and data checks (if history table is not empty). In addition, the system also performs a runtime consistency check. For more info, visit In addition, temporal checks have been added to the DBCC CHECKCONSTRAINTS statement.

13 Demo Query Optimization
SSMS > Query > Display Estimated Execution Plan Show FOR SYSTEM_TIME AS OF = Union 2 queries

14 Security Principles Principle Description
Enabling/disabling system-versioning requires highest privileges on affected objects Enabling and disabling SYSTEM_VERSIONING requires CONTROL permission on both the current and the history table History data cannot be modified directly When SYSTEM_VERSIONING is ON users cannot alter history data regardless of their actual permissions on current or the history table. This includes both data and schema modifications. Querying history data requires SELECT permission on the history table Merely because a user has SELECT permission on the current table does not mean that they have SELECT permission on the history table. Audit surfaces operations affecting history table in specific ways: Auditing on history table regularly captures all direct attempts to access the data (regardless if they were successful or not).  SELECT with temporal query extension shows that history table was affected with that operation.  CREATE/ALTER temporal table expose information that permission check happens on history table as well. Audit file will contain additional record for history table. DML operations on current table surface that history table was affected but additional_info provides necessary context (DML was result of system_versioning).

15 Query Optimization Use clustered columnstore as a primary index for windowing functions and aggregates (compression, query performance). If the primary use case is data audit (i.e. searching for historical changes for a single row from the current table), then a good choice is to create rowstore history table with a clustered index Despite all valid records were from the history table, we still see a Clustered Index Scan against the tables, causing a performance hit on both current & historical tables SELECT * FROM HumanResources.Employee_Temporal FOR SYSTEM_TIME AS OF ' :22'; This query needs to concatenate the appropriate rows from the main table with the appropriate rows from the history table. If you plan to run analytic queries on the historical data that employs aggregates or windowing functions, creating a clustered columnstore as a primary index is highly recommended for compression and query performance. Columnstore index is a new type of index introduced in SQL Server It is a column-based non-clustered index geared toward increasing query performance for workloads that involve large amounts of data, typically found in data warehouse fact tables In SQL Server, prior to 2012 all indexes were row-store, you specify what fields you want to index, and the value of the rows are evaluated to improve performance (over-simplified). These indexes speed up finding/filtering rows.

16 Best Practices For converting an existing table, consider using the HIDDEN clause to hide the new PERIOD columns to avoid impacting existing applications that are not designed to handle new columns. Caution to Closed/Open intervals ( < vs <= ) Use separate schema for History tables FOR SYSTEM_TIME filters out row versions with the same validity start and end times

17 Conclusion Let’s recap…

18 Resources MSDN Introducing Temporal Tables in SQL Server 2016 (Part 1)
Introducing Temporal Tables in SQL Server 2016 (Part 2) SQL Server 2016: Temporal Tables MSDN

19 Thank you for attending!
Contact Info @SamNasr Thank you for attending!


Download ppt "Temporal Tables Sam Nasr, MCSA, MVP NIS Technologies July 22, 2017"

Similar presentations


Ads by Google