ALTER TABLE dbo.OrderDetailCH ADD CONSTRAINT FK_OrderDetailCH_Order FOREIGN KEY LocationCode,OrderID REFERENCES dbo.OrderCHLocationCode,OrderID ALTER TABLE dbo.OrderDetailCH ADD CONSTRAI
Trang 1ALTER TABLE dbo.OrderDetailCH ADD CONSTRAINT
FK_OrderDetailCH_Order FOREIGN KEY (LocationCode,OrderID) REFERENCES dbo.OrderCH(LocationCode,OrderID) ALTER TABLE dbo.OrderDetailCH
ADD CONSTRAINT PK_OrderDetailCH PRIMARY KEY NONCLUSTERED (LocationCode, OrderDetailID)
ALTER TABLE dbo.OrderDetailCH ADD CONSTRAINT
OrderDetailCH_PartitionCheck CHECK (LocationCode = ‘CH’)
go move the data
INSERT dbo.OrderCH (LocationCode,
OrderID, OrderNumber, ContactID, OrderPriorityID, EmployeeID, LocationID, OrderDate, Closed)
SELECT
‘CH’,
OrderID, OrderNumber, ContactID, OrderPriorityID, EmployeeID, [Order].LocationID, OrderDate, Closed FROM [Order]
JOIN Location
ON [Order].LocationID = Location.LocationID
WHERE LocationCode = ‘CH’
INSERT dbo.OrderDetailCH (
LocationCode, OrderDetailID, OrderID, ProductID, NonStockProduct, Quantity, UnitPrice, ShipRequestDate, ShipDate, ShipComment)
SELECT ‘CH’,
OrderDetailID, OrderDetail.OrderID, ProductID, NonStockProduct, Quantity, UnitPrice, ShipRequestDate, ShipDate, ShipComment
FROM OrderDetail
JOIN OrderCH
ON OrderDetail.OrderID = OrderCH.OrderID Creating the partition view
With the data split into valid partition tables that include the correct primary keys and constraints,
SQL Server can access the correct partition table through a partition view TheOrderAllview uses a
UNION ALLto vertically merge data from all three partition tables:
Trang 2LocationCode,
OrderID, OrderNumber, ContactID, OrderPriorityID,
EmployeeID, LocationID, OrderDate, Closed
FROM OrderCH
UNION ALL
SELECT
LocationCode,
OrderID, OrderNumber, ContactID, OrderPriorityID,
EmployeeID, LocationID, OrderDate, Closed
FROM OrderJR
UNION ALL
SELECT
LocationCode,
OrderID, OrderNumber, ContactID, OrderPriorityID,
EmployeeID, LocationID, OrderDate, Closed
FROM OrderKDH
Selecting through the partition view
When all the data is selected from theOrderAllpartition view, the query plan, shown in Figure 68-1,
includes all three partition tables as expected:
SELECT LocationCode, OrderNumber
FROM OrderAll
Result (abridged):
LocationCode OrderNumber
-
.
What makes partition views useful for advanced scalability is that the SQL Server query processor
will use the partition tables’ check constraints to access only the required tables if the partition key is
included in theWHEREclause of the query calling the partition view
The following query selects on the Kill Devil Hills orders from the partition view TheLocationCode
column is the partition key, so this query will be optimized for scalability Even though the view’s union
includes all three partition tables, the query execution plan, shown in Figure 68-2, reveals that the query
processor accesses only theOrderCHpartition table:
SELECT OrderNumber
FROM OrderAll
WHERE LocationCode = ‘KDH’
Trang 3OrderNumber -9
10
FIGURE 68-1
The partition table’s query plan, when run without a where clause restriction, includes all the partition
tables as a standard union query
Updating through the partition view
Union queries are typically not updateable Yet, the partition tables’ check constraints enable a partition
view based on a union query to be updated, as long as a few conditions are met:
■ The partition view must include all the columns from the partition tables
■ The primary key must include the partition key
Trang 4■ Partition table columns, including the primary key, must be identical.
■ Columns and tables must not be duplicated within the partition view
FIGURE 68-2
When a query with a where clause restriction that includes the partition key retrieves data through
the partition view, SQL Server’s query processor accesses only the required tables
The followingUPDATEquery demonstrates updating through theOrderAllview:
UPDATE OrderAll
SET Closed = 0
WHERE LocationCode = ‘KDH’
Trang 5Unfortunately, anUPDATEdoes not benefit from query optimization to the extent that aSELECTdoes.
For heavy transactional processing at the stored-procedure level, the code should access the correct
partition table
Moving data
An issue with local-partition views is that data is not easily moved from one partition table to another
partition table AnUPDATEquery that attempts to update the partition key violates the check constraint:
UPDATE OrderAll SET Locationcode = ‘JR’
WHERE OrderNumber = 9 Result:
Server: Msg 547, Level 16, State 1, Line 1 UPDATE statement conflicted with TABLE REFERENCE constraint
‘FK_OrderDetailKDH_Order’ The conflict occurred in database ‘OBXKites’, table ‘OrderDetailKDH’
The statement has been terminated
For implementations that partition by region or department, moving data may not be an issue, but for
partition schemes that divide the data into current and archive partitions, it is
The only possible workaround is to write a stored procedure that inserts the rows to be moved into the
new partition and then deletes them from the old partition To complicate matters further, a query that
inserts into the partition view cannot reference a partition table in the query, so anINSERT SELECT
query won’t work A temporary table is required to facilitate the move:
CREATE PROCEDURE OrderMovePartition (
@OrderNumber INT,
@NewLocationCode CHAR(5) ) AS
SET NoCount ON DECLARE @OldLocationCode CHAR(5) SELECT @OldLocationCode = LocationCode FROM OrderAll
WHERE OrderNumber = @OrderNumber Insert New Order
SELECT DISTINCT OrderID, OrderNumber, ContactID, OrderPriorityID, EmployeeID, LocationID, OrderDate, Closed
INTO #OrderTemp FROM OrderAll WHERE OrderNumber = @OrderNumber AND LocationCode = @OldLocationCode INSERT dbo.OrderAll (LocationCode,
Trang 6EmployeeID, LocationID, OrderDate, Closed)
SELECT
@NewLocationCode,
OrderID, OrderNumber, ContactID, OrderPriorityID,
EmployeeID, LocationID, OrderDate, Closed
FROM #OrderTemp
Insert the New OrderDetail
SELECT DISTINCT
OrderDetailID, OrderDetailAll.OrderID,
ProductID, NonStockProduct, Quantity, UnitPrice,
ShipRequestDate, ShipDate, ShipComment
INTO #TempOrderDetail
FROM OrderDetailALL
JOIN OrderALL
ON OrderDetailALL.OrderID = OrderALL.OrderID
WHERE OrderNumber = @OrderNumber
Select * from #TempOrderDetail
INSERT dbo.OrderDetailAll (
LocationCode, OrderDetailID, OrderID, ProductID,
NonStockProduct, Quantity, UnitPrice, ShipRequestDate,
ShipDate, ShipComment)
SELECT @NewLocationCode,
OrderDetailID, OrderID,
ProductID, NonStockProduct, Quantity, UnitPrice,
ShipRequestDate, ShipDate, ShipComment
FROM #TempOrderDetail
Delete the Old OrderDetail
DELETE FROM OrderDetailAll
FROM OrderDetailAll
JOIN OrderALL
ON OrderAll.OrderID = OrderDetailAll.OrderID
WHERE OrderNumber = @OrderNumber
AND OrderDetailAll.LocationCode = @OldLocationCode
Delete the Old Order
DELETE FROM OrderALL
WHERE OrderNumber = @OrderNumber
AND LocationCode = @OldLocationCode
To test the stored procedure, the following batch moves order number 9 from the Kill Devils Hill store
to the Jockey’s Ridge location:
EXEC OrderMovePartition 9, ‘JR’
To see the move, the following query reports theLocationCodefrom both theOrderAlland the
OrderDetailAlltables:
Trang 7Select OrderAll.OrderNumber, OrderALL.LocationCode as OrderL, OrderDetailALL.LocationCode AS DetailL FROM OrderDetailAll
JOIN OrderAll
ON OrderAll.OrderID = OrderDetailAll.OrderID WHERE OrderNumber = 9
Result:
OrderNumber OrderL DetailL -
Distributed-partition views
Because partition views often segment data along natural geographic lines, it logically follows that
a partition view that spans multiple servers is very useful Distributed-partition views build upon
local-partition views to unite data from segmented tables located on different servers This technique is
also referred to as a federated-database configuration because multiple individual components cooperate to
complete the whole This is how Microsoft gains those incredible performance benchmarks
The basic concept is the same as that of a local-partition view, with a few differences:
■ The participating servers must be configured as linked servers with each other
■ The distributed-partition view on each server is a little different from those of the other servers, because it must use distributed queries to access the other servers
■ Each server must be configured for lazy schema validation to prevent repeated requests for metadata information about the databases
Turning on lazy schema validation means that SQL Server will not check remote tables for the proper schema until it has executed a script This means that if a remote table has changed, then scripts that depend on that table will error out Turning this feature on can result in
certain bad effects on scripts but does help increase performance.
The following script configures a quick distributed-partition view betweenMauiandMaui\
Copenhagen(my two development instances) To save space, I list only theMauihalf of the script
Similar code is also run on the second server to establish the distributed view The script creates a
database with a single table and inserts a single row Once a link is established, and lazy schema
validation is enabled, the distributed-partition view is created This partition view is created with a
four-part name to access the remote server Selecting through the distributed-partition view retrieves
data from both servers:
CREATE DATABASE DistView
go
Trang 8CREATE TABLE dbo.Inventory(
LocationCode CHAR(10) NOT NULL,
ItemCode INT NOT NULL,
Quantity INT )
ALTER TABLE dbo.Inventory
ADD CONSTRAINT PK_Inventory
PRIMARY KEY NONCLUSTERED(LocationCode, ItemCode)
ALTER TABLE dbo.Inventory
ADD CONSTRAINT Inventory_PartitionCheck
CHECK (LocationCode = ‘MAUI’)
INSERT dbo.Inventory
(LocationCode, ItemCode, Quantity)
VALUES (’MAUI’, 12, 1)
Link to the Second Server
EXEC sp_addlinkedserver
@server = ‘MAUI\COPENHAGEN’,
@srvproduct = ‘SQL Server’
EXEC sp_addlinkedsrvlogin
@rmtsrvname = ‘MAUI\COPENHAGEN’
Lazy Schema Validation
EXEC sp_serveroption ‘MAUI\COPENHAGEN’,
‘lazy schema validation’, true
Create the Distributed Partition View
CREATE VIEW InventoryAll
AS
SELECT *
FROM dbo.Inventory
UNION ALL
SELECT *
FROM [MAUI\COPENHAGEN].DistView.dbo.Inventory
SELECT *
FROM InventoryAll
Result:
LocationCode ItemCode Quantity
-
MAUI\COPENHAGEN 14 2
Updating and moving data with distributed-partition views
One fact that makes distributed-partition views an improvement over local-partition views is that a
distributed-partition view can move data without complication MS Distributed Transaction Coordinator
must be running andxact_abortenabled because the transaction is a distributed transaction The
following update query changes theLocationCodeof the first server’s row toMaui\Copenhagen,
and effectively moves the row fromMauitoMaui\Copenhagen:
Trang 9SET XACT_ABORT ON UPDATE InventoryAll SET LocationCode = ‘MAUI\COPENHAGEN’
WHERE Item = 12
To show you the effect of the update query, the next query selects from the distributed-partition view
and demonstrates that item 14 is now located onMaui:
SELECT * FROM InventoryAll Result:
LocationCode ItemCode Quantity -
Highly scalable distributed-partition views
SQL Server’s query processor handles distributed-partition views much like it handles local-partition
views Where the local-partition view accesses only the required tables, a distributed-partition view
performs distributed queries and requests the required data from the remote servers Each server
executes a portion of the query
In the following example, the query is being executed onMaui A remote query request is sent to
Maui\Copenhagen, and the results are passed back toMaui The query processor knows not to
bother looking at the table onMaui Even better, the query passes the row restriction to the remote
server as well.Maui\Copenhagenhas two rows, but only one is returned:
SELECT * FROM InventoryAll WHERE LocationCode = ‘MAUI\COPENHAGEN’
AND Item = 14 Result:
LocationCode ItemCode Quantity -
Partitioned Tables and Indexes
Partitioned tables are similar to partitioned views — both involve segmenting the data However,
whereas partitioned views store the data in separate tables and use a view to access the tables,
partitioned tables store the data in a segmented clustered index and use the table to access the data
Partitioning tables reduces the sheer size of the clustered and non-clustered b-tree indexes, which
Trang 10■ Inserts and update operations must also insert and update index pages When a table is
partitioned, only the affected partition’s indexes are updated
■ Index maintenance can be a costly operation A partition’s index is significantly smaller
and reduces the performance cost of reindexing or defragmenting the index However, the
partitions can’t be indexed off-line, which is still a major drawback
■ Backing up part of a table using Backup Filegroups eases backups
■ The index b-tree is slightly smaller — perhaps an intermediate level or two smaller — but the
performance gain is probably not going to be noticeable
■ A partitioned table can segment the data by oneWHEREclause filter and perhaps improve the
selectiveness of another filtering predicate so that the index is used when perhaps it wasn’t
without partitioning
■ With partitioned data, a scan might only need to retrieve a partition, rather than the entire
table, which can result in a huge performance difference and avoid memory bloat
Best Practice
The performance benefit of partitioned tables doesn’t kick in until the table is extremely large — billion-row
tables in terabyte-size databases In fact, in some testing, partitioned tables actually hurt performance on
smaller tables with less than a million rows, so reserve this technology for the big problems Maybe that’s
why table partitioning isn’t included in Standard Edition
On the other hand, even for tables with fewer than one million rows, partitioning can be an effective part of
archiving old data into one partition while keeping current data in another partition
Creating SQL Server 2008 table partitions is a straightforward four-step process:
1 Create the partition function that will determine how the data is partitioned.
2 Create the partition scheme that assigns partitions to filegroups.
3 Create the table with a non-clustered primary key.
4 Create a clustered index for the table using the partition scheme and partition function.
Partition functions and partition schemes work together to segment the data as illustrated in
Figure 68-3
Creating the partition function
A partition function is simply a means to define the range of values that each partition will contain A
table partition can segment the data based on a single column Even though the table isn’t yet defined,
the function must know the segmenting column’s data type, so the partition function’s parameter is the
data type that will be used to segment the data
In the following example, the functionfnYearstakes a datetime value The function defines the
boundary values for the ranges of each partition An important aspect of boundary values is that you