понедельник, 30 августа 2010 г.

Увольняюсь …..

 

Да!!! Решил все таки уволится.

Почему?

Есть несколько причин. Ну во-первых не устраивает зп, во вторых наше руководство, которое вдруг стало себя считать самым умным(не ну пусть считают, молодцы, но только не надо показывать это людям,  особенно тем, которые знают твой уровень знаний  -становится очень смешно), в третьих – надо как-то двигаться, я в принципе закончил свои дела  на этой фирме: перевел ее на новый сайт, перевел на новую версию Олап, нашел отличного клиента для олап и т.д. Хватит надо  двигаться дальше и развиваться, а то превратишься …….

В общем к новым знаниям, к новому коллективу(хотя старый мне тоже нравился и мне его будет не хватать)

четверг, 26 августа 2010 г.

Работа с партициями в MSAS 2008

 

Всем привет.

Сегодня хочу описать  небольшой скрипт, который я написал для работы с партициями MSAS.

Предыстория

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

as1

Для каждой партиции указан источник:

SELECT *   FROM [dbo].[таблица]   WHERE year(Дата)<=2004

То есть фактически каждая партиция содержит данные за определенный год. Что же касается текущего то, тут чуть другая ситуация.

Для текущего года, на картинки part_2010 источник  другой

SELECT   * FROM  [dbo].[таблица]
  WHERE
(Year(Дата)=2010 ) and   ( (Month(Дата)>=1) and  (Month(Дата)<=6))

а партиция prev  содержит источник за предыдущий месяц и current за текущий.

Такая структура  позволяет обновлять только  2 партиции(текущую и предыдущую) и отказаться от полного процессинга куба.

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

Задача

Необходимо написать скрипт, который бы создавал новую партицию и изменял бы в источнике данных запрос

Решение

Решением стал  скрипт, написанный на C# с использованием AMO

   1: public void Main()
   2:        {
   3:            // TODO: Add your code here
   4:            Dts.TaskResult = (int)GetAS();
   5:        }
   6://создание партиции год
   7:        public bool CreatePartitionYear(Cube cubePartition)
   8:        {
   9:            Partition partYear = new Partition("part_" + DateTime.Now.Year.ToString());//создаем объект партиции и назвначаем ему имя
  10:            Microsoft.AnalysisServices.QueryBinding query = new QueryBinding();// создаем объект, отвечающий за источник
  11:            query.DataSourceID = cubePartition.DataSource.ID;//указываем  id источника
  12:            partYear.StorageMode = StorageMode.Molap;//указываем тип партции
  13:            query.QueryDefinition = "SELECT  * FROM [dbo].[таблица] WHERE (Year(Дата)=" + DateTime.Now.Year.ToString() + " ) and   (Month(Дата)=1) ";//указываем собственно запрос
  14:            partYear.Source = query;// присваевается объект источника  партиции
  15:            try
  16:            {
  17:                cubePartition.MeasureGroups[0].Partitions.Add(partYear);//добавляем партицию в куб
  18:                partYear.Update();//отправляем новое определение объекта на сервер
  19:                partYear.Update(UpdateOptions.AlterDependents);// на всякий случай
  20:                cubePartition.MeasureGroups[0].Update(UpdateOptions.AlterDependents);//обновляем структуру секций
  21:                cubePartition.Update();//обновляем  структуру куба
  22:                cubePartition.Refresh();//делаем синхронизацию объектов  Amo и as
  23:                cubePartition.MeasureGroups[0].Refresh();//делаем синхронизацию объектов  Amo и as
  24:            }
  25:            catch (Exception exp)
  26:            {
  27:                return false;
  28:            }
  30:            Partition partNew;
  32:            partNew = cubePartition.MeasureGroups[0].Partitions.FindByName("prev");// ищем  партицию prev
  33:            try
  34:            {
  35:                if (partNew != null) partNew.Drop();//если существуе, удаляем
  36:            }
  37:            catch (Exception exp)
  38:            {
  40:            }
  41:            partNew = cubePartition.MeasureGroups[0].Partitions.Add("prev");// добавляем партицию
  42:            partNew.StorageMode = StorageMode.Molap;// указываем тип партции
  43: /создаем запрос для источника партиции
  44:            Microsoft.AnalysisServices.QueryBinding queryPrev = new QueryBinding();
  45:            queryPrev.QueryDefinition = "SELECT  * FROM [dbo].[Таблица] WHERE (Year(Дата)=" + DateTime.Now.Year.ToString() + " ) and   (Month(Дата)=" + (DateTime.Now.Month - 1).ToString() + ") ";
  46:            queryPrev.DataSourceID = cubePartition.DataSource.ID;
  47:            partNew.Source = queryPrev;
  49:            partNew.Update();//обновляем структур
  50:            cubePartition.MeasureGroups[0].Update(UpdateOptions.AlterDependents);//обновляем структуру секций
  51:            cubePartition.Update();//обновляем структуру куба
  52:            cubePartition.Refresh();//синхронизируем объекты
  53:            cubePartition.MeasureGroups[0].Refresh();//синхронизируем объекты         
  54:            return true;
  55:        }
  56: /создание партиции месяц
  57:        public bool CreatePartitionMonth(Cube cubePartition)
  58:        {
  59:            Partition part = cubePartition.MeasureGroups[0].Partitions.FindByName("part_" + DateTime.Now.Year.ToString());//ищем партцию текущего года
  60:            if (part != null)
  61:             {
  62:                        Partition partPrev = cubePartition.MeasureGroups[0].Partitions.FindByName("prev");//ищем партицию prev
  63:                        List<Partition> lspPart = new List<Partition>();//список партиций
  64:                        Microsoft.AnalysisServices.QueryBinding query = new QueryBinding();//объект  источник для партиции года
  65:                        query.DataSourceID = cubePartition.DataSource.ID;
  66:                        if ((DateTime.Now.Month == 1))//проверка на месяц
  67:                        {
  68: //Сделано для того, чтобы не возникала ситуация 1-2(текущий месяц январь(01, то есть 1), для вычисления  месяца, который был 2 месяца назад, то есть 1-2=-1 и получаем exception. Да можно было бы от этого избавится и использовать функции месяца и вычислять минус 62 дня, но так наглядней и понятней
  69:                            query.QueryDefinition = "SELECT  * FROM [dbo].[таблица] WHERE (Year(Дата)=" + (DateTime.Now.Year-1).ToString() + " ) and   (Month(Дата)=11) ";
  70:  
  71:                        }
  72:                        else
  73:                        {
  74:                            if ((DateTime.Now.Month == 2))//проверка на второй месяц. 
  75:                            {
  76:                                query.QueryDefinition = "SELECT  * FROM [dbo].[таблица] WHERE (Year(Дата)=" + (DateTime.Now.Year - 1).ToString() + " ) and   (Month(Дата)=12) ";
  77:                            }
  78:                            else
  79:                            {
  80:                                query.QueryDefinition = "SELECT  * FROM [dbo].[таблица] WHERE (Year(Дата)=" +
  81:                                    DateTime.Now.Year.ToString() + " ) and   ((Month(Дата)>=1) and (Month(Дата)<=" + (DateTime.Now.Month - 2).ToString() + ")) ";
  82:                            }
  83:                        }
  84:                        part.Source = query;
  86:                 lspPart.Add(partPrev);
  88:                        try
  89:                        {
  90:                            part.Merge(lspPart);//сливаем партиции
  91:                            part.Update(UpdateOptions.AlterDependents);//обновляем структуру секции год
  92:                            cubePartition.MeasureGroups[0].Update(UpdateOptions.AlterDependents);//обновляем структуру секций
  93:                            cubePartition.Update();//обновляем структур куба
  94:                            cubePartition.Refresh();//синхронизация
  95:                            cubePartition.MeasureGroups[0].Refresh();//синхронизация
  97:                        }
  98:                        catch(Exception exp)
  99:                        {
 100:                            string message = exp.Message;
 101:                            return false;
 102:                        }
 104:                        try
 105:                        {
 106:              //здесь создаем партицию prev             
 107:                             Partition partNew;
 108:                            
 109:                            partNew =cubePartition.MeasureGroups[0].Partitions.FindByName("prev");
 110:                            try
 111:                            {
 112:                                if (partNew != null) partNew.Drop();
 113:                            }
 114:                            catch (Exception exp)
 115:                            {
 116:                                
 117:                            }
 118:                            partNew = cubePartition.MeasureGroups[0].Partitions.Add("prev");
 119:                            partNew.StorageMode = StorageMode.Molap;
 120:                            
 121:                            Microsoft.AnalysisServices.QueryBinding queryPrev = new QueryBinding();
 122:                            queryPrev.QueryDefinition = "SELECT  * FROM [dbo].[таблица] WHERE (Year(Дата)=" + DateTime.Now.Year.ToString() + " ) and   (Month(Дата)=" + (DateTime.Now.Month - 1).ToString() + ") ";
 123:                            queryPrev.DataSourceID = cubePartition.DataSource.ID;
 124:                            partNew.Source = queryPrev;
 126:                            partNew.Update();
 127:                            cubePartition.MeasureGroups[0].Update(UpdateOptions.AlterDependents);
 128:                            cubePartition.Update();
 129:                            cubePartition.Refresh();
 130:                            cubePartition.MeasureGroups[0].Refresh();
 132:                        }
 133:                        catch (Exception exp)
 134:                        {
 135:                            string message = exp.Message;
 136:                            return false;
 137:                        }
 139:             }
 140:             return true;
 141:        }
 142:  
 143:/ /процессинг партиций
 144:        public bool ProccesPartition(Cube cubePartition)
 145:        {
 146:            Partition partPrev = cubePartition.MeasureGroups[0].Partitions.FindByName("prev");//ищем партицию
 147:            if (partPrev != null)
 148:            {
 149:                partPrev.Process(ProcessType.ProcessFull);//делаем полный процессинг
 150:            }
 151:            else
 152:            {
 153:                return false;
 154:            }
 156:            Partition parCurrent = cubePartition.MeasureGroups[0].Partitions.FindByName("current");//ищем партицию
 157:            if (parCurrent != null)
 158:            {
 159:                parCurrent.Process(ProcessType.ProcessFull);//полный процессинг
 160:  
 161:            }
 162:            else
 163:            {
 164:                return false;
 165:            }
 167:            return true;
 169:        }
 170:  
 172:        public int GetAS()
 173:        {
 174:            using(Server srv=new Server())
 175:            {
 176:                srv.Connect("localhost");//коннектимся к серверу
 177:                Database db = srv.Databases.GetByName("ИмяБазы");//конектимся к базе
 178:                if (db != null)
 179:                {
 180:                    Cube cubeOverturn = db.Cubes.GetByName("ИмяКубика");//ищем кубик
 181:                    if (cubeOverturn != null)
 182:                    {
 183:                        DateTime dt = DateTime.Now;//определяем текущее время
 184:                        if (dt.Day == 1)
 185:                        {
 186:                            if (dt.Month == 3)
 187:                            {
 188:                                if (!CreatePartitionYear(cubeOverturn))//создаем партцию года
 189:                                {
 190:                                    srv.Disconnect();
 191:                                    return (int)ScriptResults.Failure;
 192:                                }
 193:                                else
 194:                                {
 195:                                    ProccesPartition(cubeOverturn);//процессим партиции
 196:                                }
 197:                            }
 198:                            else
 199:                            {
 200:                                if (!CreatePartitionMonth(cubeOverturn))//создаем партиции месяца
 201:                                {
 202: /произошла ошибка
 203:                                    srv.Disconnect();//разрываем связь
 204:                                    return (int)ScriptResults.Failure;//возвращаем fail
 205:                                }
 206:                                else
 207:                                {
 208:                                    ProccesPartition(cubeOverturn);//процессим
 209:                                }
 210:                            }
 211:                        }
 212:                        else
 213:                        {
 214:                            if (!ProccesPartition(cubeOverturn))//просто процессим
 215:                            {
 216:                                srv.Disconnect();
 217:                                return (int)ScriptResults.Failure;
 218:                            }
 220:                        }
 221:                    }
 222:                    else
 223:                    {
 224:                        srv.Disconnect();
 225:                        return (int)ScriptResults.Failure;
 226:                    }
 228:                }
 229:                else
 230:                {
 231:                    srv.Disconnect();
 232:                    return (int)ScriptResults.Failure;
 233:                }
 234:                srv.Disconnect();
 235:            }
 238:            return (int)ScriptResults.Success;
 239:        }
 242:    }

Да, я знаю, что код можно было бы упростить. Сделать рефакторинг, но  этот будет все потом(нет времени). Сейчас скрипт работает нормально на  моей базе.