SQL Server横向扩展:设计,实现与维护(3)- 分布式分区视图的实现
SQL Server横向扩展:设计,实现与维护(3)- 分布式分区视图的实现
在上一篇文章中,我们已经说到分布式分区视图采用的是Linked Server技术实现,也大致的说了下它的实现原理,我们这里对实现的内部机制点到为止,我们本系列的目的在于实战和分析各种技术方案的使用场景。
一般而言,我们常常会使用SQL Profiler来对Linked Server进行故障排除和性能优化。在SQL Server 2005以及之后版本中,增强了查看Linked Server工作情况的事件。通过Profiler,我们可以看到OLE DB调用其他数据库服务器的信息。
查询的执行过程
其实,分布式分区视图就是将一个查询中的生成的查询树的一部分传递到远程的数据库中。这个道理大家应该很容易想到。在SQL Server 2000中,一个查询的启动命令和查询的获取数据行命令不能并行的进行。在SQL Server 2005以及以后,命令的启动可以并行的执行,而且远程数据库的连接池和重叠使用的I/O是经过优化了的。但是,依然不能并行的执行命令去获取数据。
大家可能不是太明白这里的讲述,我下面就举个简单的例子说明下:
假设现在有一个使用了Linked Server的查询,那么生成的查询树(注意,这里是查询树,是逻辑的语法树,还不是执行计划)我们假设如下:
大家看到图中标注红色的部分,代表了这里的查询树需要最终去远程数据库上面执行。
当查询树生成好了之后,就需要去执行,此时,这个查询树就要被分拆到不同的远程数据库上面去,此时在2005中,假设上面的查询树需要连接4个不同的远程数据库,那么此时,那么,此时,就可以并行的启动四个查询的命令,然后这些命令将各自的查询树结构传递过去。然后这些查询树就会交给远程的数据库查询引擎去优化,然后执行,之后远程的数据库就会把数据传送回来,但是此时这个4个远程数据库不能同时传送数据,只能一个个的来。
而且,在这个过程中SQL Server OLE DB会把“获取的数据行的统计信息”发送到远程的SQL Server中,去帮助远程的数据库的查询处理器更好的工作,从而使得,从远程情况下,允许有统计查询处理器执行相同的查询与本地查询的成本估算和优化,并选择最有效的整体查询计划。
实现分布式分区视图
要实现分布式分区视图,我们就需要使用Linked Server,为了建立Linked Server,我们可以使用很多的方式:直接使用图形化的SSMS界面,然后中对象浏览器中创建;使用sp_addlinkedserver这个存储过程。
在SSMS中,我们可以很容易的申明要连接的数据库实例的名字,而且还需要将Server Type设置为SQL Server。使用SSMS建立Linked Server的时候,很多的配置都是采用默认值,但是当使用sp_addlinkedserver的时候,我们需要配置相关的参数,特别是要设置svrproduct,这个参数的值必须是SQL Server。
下面就看个例子,使用存储过程建立的,代码如下:
USE MASTER
GO
EXECUTE sp_addlinkedserver 'ServerB', N'SQL Server'
GO
-- on instance B
USE MASTER
GO
EXECUTE sp_addlinkedserver 'ServerA', N'SQL Server'
GO
然后,我们需要在每个数据库中都去建立相同的数据表,因为我们现在演示的例子是把一个表中的数据拆分放在不同的服务器上面(当然,我们还可以把原本在一个数据库的表放在不同的数据库中)。当我们把一个表拆分放在不同的数据库时,需要制定一个拆分的条件,这一点和我们在SQL Server 2005的分区表中使用分区方案类似,但是这里的分区是分布式的,例如,对于Customer表,我们把CustomerID作为拆分的列,如下:
USE SalesDB
GO
CREATE TABLE SalesSchema.Customers1to4 (
-- partitioning column
CustomerId INTEGER PRIMARY KEY
CHECK (CustomerID BETWEEN 1 AND 49999),
-- other columns…
)
-- on instance B
USE SalesDB
GO
CREATE TABLE SalesSchema.Customers5to9 (
-- partitioning column
CustomerId INTEGER PRIMARY KEY
CHECK (CustomerID BETWEEN 50000 AND 99999),
-- other columns…
)
USE SalesDB
GO
CREATE TABLE SalesSchema.Customers1to4 (
-- partitioning column
CustomerId INTEGER PRIMARY KEY
CHECK (CustomerID BETWEEN 1 AND 49999),
-- other columns…
)
-- on instance B
USE SalesDB
GO
CREATE TABLE SalesSchema.Customers5to9 (
-- partitioning column
CustomerId INTEGER PRIMARY KEY
CHECK (CustomerID BETWEEN 50000 AND 99999),
-- other columns…
)
上面的代码应该很好理解:把CustomerID从1到49999的用户放在数据库实例A中,50000-99999的用户放在B中。
数据分布好了之后,我们就需要去建立视图,从而向应用程序那边隐藏内部的实现,代码如下:
USE SalesDB
GO
CREATE VIEW AllCustomers AS
SELECT * FROM SalesDB.SalesSchema.Customers1to4
UNION ALL
SELECT * FROM ServerB.SalesDB.SalesSchema.Customers5to9
)
-- on instance B
USE SalesDB
GO
CREATE VIEW AllCustomers AS
SELECT * FROM ServerA.SalesDB.SalesSchema.Customers1to4
UNION ALL
SELECT * FROM SalesDB.SalesSchema.Customers5to9
)