2011-08-25 75 views
3

我们有一个在SQL Server 2008 R2 SE称为AVL数据库。这个数据库有许多表,但有一个在现在有46个永行,占总数据库大小的99.9%,特别是在所谓ASSETLOCATION。SQL Server 2008中的动态跨数据库查看

该表格包含2008年至今的信息,实际增长速度每天约为12万条记录。 现在,有2种情况,我们谈谈:

  • 性能也开始慢慢退化,一切 优化,所以没有太多的做
  • 备份时间正在增加,并成为一个问题(我们每天备份1个完整的 )。该BAK文件是11GB,winrar的做他的事 最终大小2GB后,然后脚本将文件发送到场外。我们有一个 T1和拉动2GB通过导线走约5小时。

这一切都是正常的,但这里是我想利用的捕获:+ 90%的SQL语句使用的信息只有3个月或更少,换句话说,2008年,2009年和2010年的数据没有得到经常访问。

我正在考虑为每年创建一个新的数据库。比方说: - AVL2008数据库,只有表会有ASSETLOCATION与记录从2008年 - AVL2009数据库,只有表会有ASSETLOCATION与记录从2009年 - AVL2010数据库,只有表会有ASSETLOCATION与记录从2010年

正如你已经猜到了,从过去的数据没有得到改变,所以这将是从备份的角度很大,因为AVL数据库将只能从当年的记录。这种方法也将有助于提高性能。

现在的问题。假设ASSETLOCATION表有以下几列: - IDASSETLOCATION(INT,PK身份) - IDASSET(INT,FK资产表) - 当(日期时间) - 经纬度(VARCHAR(22),空间信息)

我需要在名为“vassetLOCATION”的AVL数据库中创建一个视图,相当简单,但我不希望视图访问所有数据库并通过UNION加入ASSETLOCATION表,而只需要基于WHEN字段。例如:

select * from vASSETLOCATION where [WHEN] between '2008-01-01' and '2008-01-02' 

在这种情况下,视图应只能访问AVL2008.ASSETLOCATION表

select * from vASSETLOCATION where [WHEN] between '2008-12-29' and '2009-01-05' 

在这种情况下,视图应该访问AVL2008.ASSETLOCATION和AVL2009.ASSETLOCATION

select * from vASSETLOCATION where 
    ([WHEN] between '2008-01-01' and '2008-01-01') 
or 
    ([WHEN] = getdate()) 

在这种情况下,视图应该访问AVL2008.ASSETLOCATION和AVL.ASSETLOCATION

我知道一个表标量UDF代替视图将解决问题,但是不止有4个字段,并且[WHEN]不是我们可能想要包含在where部分中的唯一字段。 之前有人建议它,表分区功能将可能在性能上有所帮助,但不是在备份的问题。

如果有一种方式,为了做到这一点? 谢谢.-

+1

参照你对表分区的评论一想,这可能会帮助你的备份问题,如果你使用的分区方案,以独立分散在不同的文件组中的数据,然后备份文件组(可能对不同的方案)。至少要研究一些东西。 –

+0

@WT_W绝对地说,分区并不一定意味着“备份是巨大的”......当然有办法布置分区和文件组,以便旧数据是只读的而不是活动备份例程的一部分。 –

回答

2

这听起来像是一个经典案例table partitioningdistributed partitioned views

但是你可以解决此不使用一些聪明的代码,看问题的方式有点不同ponying了价格为企业版(或做所有为支持这些功能所需要的准备工作)。您不希望单个视图访问不同数据库中的所有表,但如果您有多个视图和一个存储过程来控制访问方式,该怎么办?

创建视图的最常见的访问模式。也许你有涵盖的日期范围为2008 - 2010年期,2008- 2009年,2009- 2010年,等他们可能是这样的:

CREATE VIEW dbo.vAL_2008_2009 
AS 
    SELECT * FROM AVL2008.dbo.ASSETLOCATION 
    UNION ALL 
    SELECT * FROM AVL2009.dbo.ASSETLOCATION; 
GO 

CREATE VIEW dbo.vAL_2008_2010 
AS 
    SELECT * FROM AVL2008.dbo.ASSETLOCATION 
    UNION ALL 
    SELECT * FROM AVL2009.dbo.ASSETLOCATION 
    UNION ALL 
    SELECT * FROM AVL2010.dbo.ASSETLOCATION; 
GO 
-- etc. etc. 

现在你的代码处理该查询可以获取用户输入的日期参数并计算它需要查询哪个视图。例如:

CREATE PROCEDURE dbo.DetermineViews 
    @StartDate  DATETIME, 
    @EndDate  DATETIME, 
    @optionalToday BIT = 0 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE @sql NVARCHAR(MAX) = N''; 

    SET @sql = @sql + N'SELECT * FROM ' + CASE 
     WHEN @StartDate >= '20080101' AND @EndDate < '20090101' THEN 'AVL2008.dbo.ASSETLOCATION' 
     WHEN @StartDate >= '20080101' AND @EndDate < '20100101' THEN 'dbo.vAL_2008_2009' 
     WHEN @StartDate >= '20080101' AND @EndDate < '20110101' THEN 'dbo.vAL_2008_2010' 
     -- etc. etc. 

     WHEN YEAR(@StartDate) = YEAR(CURRENT_TIMESTAMP) THEN 'AVL.dbo.ASSETLOCATION' 
    ELSE '' END; 

    IF @OptionalToday = 1 AND YEAR(@StartDate) <> YEAR(CURRENT_TIMESTAMP) 
    BEGIN 
     SET @sql = @sql + N'UNION ALL SELECT * FROM AVL.dbo.ASSETLOCATION' 
    END 

    SET @sql = @sql + ' WHERE [WHEN] BETWEEN ''' 
     + CONVERT(CHAR(8), @StartDate, 112) + ''' AND ''' 
     + CONVERT(CHAR(8), @EndDate, 112) + ''''; 

    IF @OptionalToday = 1 
    BEGIN 
     SET @sql = @sql + ' OR ([WHEN] >= DATEDIFF(DAY, 0, CURRENT_TIMESTAMP) 
      AND [WHEN] < DATEADD(DAY, 1, DATEDIFF(DAY, 0, CURRENT_TIMESTAMP)'; 
    END 

    PRINT @sql; 
    -- EXEC sp_executeSQL @sql; 
END 
GO 

我可能错过了一些业务逻辑的,你一定会想添加一些错误处理在那里和测试垃圾出来,但是这是一个比较了解快速这种解决方案只需要进行更新,即创建一个新的数据库来归档去年的数据,这听起来似乎只发生在一年一次。

+0

+1 for clever!,但我需要大量更改所有使用AL表的SP。例如,当前的sql就像'select max(WHEN)from AL',其中IDASSET = 1和[WHEN]在x和y'之间需要很多工作来转换为这种方法。这看起来很像桌面标量UDF方法,但包装在SP中。 – Nick

+0

嗯,我很乐意与你会发现一个神奇的子弹,不需要工作,以您的现有查询的信心,激励你,但我不认为这将是可能的 - 你不能使用动态SQL内一个视图或一个功能。这些MAX()查询今天如何工作? –

+0

如何在SP执行期间创建临时视图?让我们说一个UDF recivies WHEN的值,并创建一个动态的视图,并发送视图名称回SP消耗... ???是否有不断创建和删除视图的性能问题? – Nick