云计算 频道

如何对SQL Azure中的数据进行垂直分区

  【IT168 微软云计算博客征文活动专稿】SQL Azure目前只支持1GB和10GB大小的数据库,如果你想在SQL Azure中存储更多的数据,可以将你的表进行拆分,然后将表的不同部分分别放到多个SQL Azure数据库上。本文将讨论如何使用一个中间层通过LINQ连接到不同数据库上的两个表,这项技术涉及到对SQL Azure中的数据进行垂直分区。

  这里我们将方案(Schema)中的所有表拆解到两个或更多SQL Azure数据库上,再选择哪些表组合到一起放在某个数据库上时,你需要了解每张表的大小,以及它们的增长速度,我们的目标是进行平均分配,使每个数据库的大小保持基本一致。

  对表进行分区后,性能方面也会有提高,因为SQLAzure在不同物理机器上分散了你的数据库,通过对工作量进行分解,你可以获得更多的CPU和内存资源。例如,如果你将你的数据库划分成10个1GB的SQL Azure数据库,你将获得10倍的CPU和内存资源。我们来看一个案例 TicketDirect ( http://www.microsoft.com/casestudies/Case_Study_Detail.aspx?CaseStudyID=4000005890 ),在高峰阶段,他们将工作量分解到数百个SQL Azure数据库上。

  跨SQL Azure数据库分解你的工作量时,你会失去在单一数据库上托管所有表的某些功能,使用这项技术时,需要考虑以下这些内容:

  · 跨数据库的外键是不支持的,换句话说就是,数据库1中表的主键不能作为数据库2中表的外键引用,SQL Server跨数据库外键支持有着同样的限制。

  · 不能有跨数据库的事务,即使你在客户端使用了分布式事务管理器也不行,这意味着如果在数据库2上的插入操作失败,你不能在数据库1上执行插入操作的回滚。这个限制可以通过客户端编码消除掉,你需要捕捉异常,并在成功完成语句的数据库上执行“undo”脚本。

  SQLAzureHelper 类

  为了实现垂直分区,我们引入 SQLAzureHelper 类,它:

  · 实现了前向只读游标;

  · 支持 IEnumerable 和LINQ;

  · 当不再需要结果集时,处理连接和数据读取器。

  使用前向只读游标可以提高性能,这意味着直到需要数据时,才会从SQL Azure中提取数据。从 SQLAzureHelper 类获得结果集的代码如下:

    var colorDataReader = SQLAzureHelper.ExecuteReader(
        ConfigurationManager.ConnectionStrings[
"ColorDatabase"].ConnectionString,
        sqlConnection
=>
        {
            SqlCommand sqlCommand
=
                
new SqlCommand("SELECT ColorName, CompanyId FROM Colors",
                    sqlConnection);
            return (sqlCommand.ExecuteReader());
        });
    
    var companyDataReader
= SQLAzureHelper.ExecuteReader(
        ConfigurationManager.ConnectionStrings[
"CompanyDatabase"].ConnectionString,
        sqlConnection
=>
        {
            SqlCommand sqlCommand
=
                
new SqlCommand("SELECT CompanyId, CompanyName FROM Companies",
                    sqlConnection);
            return (sqlCommand.ExecuteReader());
    });

 

  使用LINQ连接时,从两个SQL Server数据库返回结果集。

  LINQ

  LINQ是.NET框架的一套扩展,包含语言集成查询,设置和转换操作,它用本地语言语法扩展了C#和Visual Basic的查询功能,并提供了类库使用这些功能,下面的代码使用LINQ作为客户端查询处理器执行连接和查询两个结果集。

    var query =
        from color in colorDataReader
        
join company in companyDataReader on
            (Int32)color[
"CompanyId"] equals (Int32)company["CompanyId"]
        
select new
        {
            ColorName
= (string)color["ColorName"],
            CompanyName
= (string)company["CompanyName"]
        };
    
    foreach (var combo in query)
    {
        Console.WriteLine(
String.Format("{0} - {1}", combo.CompanyName, combo.ColorName));
}

 

  获得结果集后,通过 CompanyId 将两个结果集连接起来,然后再选择由 CompanyName 和 ColorName 组成的新类。

0
相关文章