SQL Server 2008 динамическое представление базы данных - PullRequest
3 голосов
/ 25 августа 2011

У нас есть база данных под названием AVL в SQL Server 2008 R2 SE.В этой базе данных есть много таблиц, но есть одна, в частности, под названием ASSETLOCATION, которая в настоящее время имеет 46 миллионов строк и составляет 99,9% от общего размера базы данных.

Эта таблица содержит информацию с 2008 года по настоящее время и фактическуюскорость роста составляет около 120 тысяч записей в день.Теперь есть две ситуации, к которым мы хотели бы обратиться:

  • Производительность начинает медленно снижаться, и все оптимизируется, так что делать особо нечего
  • Время резервного копирования увеличивается и становится все более быстрым.проблема (мы делаем 1 полную резервную копию каждый день).Размер файла BAK составляет 11 ГБ, после того, как winrar делает свое дело, его размер составляет 2 ГБ, а затем скрипт отправляет файл вне сайта.У нас есть T1, и на протяжение 2 ГБ через провод уходит около 5 часов.

Все это нормально, но вот ловушка, на которой я хочу извлечь выгоду: + 90% операторов SQL используют информацию только за 3 месяцастарые или менее, другими словами, данные за 2008, 2009 и 2010 гг. не часто доступны.

Я думал о создании одной новой базы данных на каждый год.Допустим: - база данных AVL2008, только таблица будет ASSETLOCATION с записями за 2008 год - база данных AVL2009, только таблица будет ASSETLOCATION с записями за 2009 год - база данных AVL2010, только таблица будет ASSETLOCATION с записями с 2010 года

Как вы уже догадались, данные из прошлого не меняются, поэтому это будет здорово с точки зрения резервного копирования, поскольку база данных AVL будет иметь записи только за текущий год.Этот подход также сильно повысит производительность.

Теперь к проблеме.Предположим, что таблица ASSETLOCATION имеет следующие столбцы: - IDASSETLOCATION (int, идентификатор PK) - IDASSET (int, таблица FK to ASSET) - WHEN (datetime) - LATLONG (varchar (22), пространственная информация)

IМне нужно создать представление в базе данных AVL под названием "vASSETLOCATION", ведь это довольно просто, , но я не хочу, чтобы представление получало доступ ко всем базам данных и присоединялось к таблицам ASSETLOCATION через UNION , точнее, единственные необходимыена основе поля КОГДА.Например:

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 Ответ

2 голосов
/ 25 августа 2011

Это похоже на классический случай разбиения таблицы или распределенных многораздельных представлений .

Тем не менее, вы можете обойти эту проблему без понижения цены на версию Enterprise (или не выполнив всю подготовительную работу, необходимую для поддержки этих функций), используя некоторый умный код, который смотрит на проблему немного по-другому. Вам не нужно одно представление, которое обращается ко всем таблицам в разных базах данных, но что, если у вас есть несколько представлений и хранимая процедура для контроля доступа к ним?

Создание представлений для наиболее распространенных шаблонов доступа. Возможно, у вас есть представление, которое охватывает диапазоны дат для 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

Возможно, мне не хватает вашей бизнес-логики, и вы наверняка захотите добавить туда некоторую обработку ошибок и протестировать ее, но это относительно простое в обслуживании решение, которое требует только обновление, которое совпадает с созданием новой базы данных для архивации прошлогодних данных, что, как кажется, происходит только один раз в год.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...