Data Warehouse

Upcoming Events

  • No events in this tag
  • thoughts on “Data Warehouse

    1. Andrey Korshikov

      Спасибо. Спасибо за поддержку. Всё только начинается. В ближайшие дни нам с тобой предстоит выступить на http://sqlrally2012.ru, приходите или смотрите нас онлайн.

      Reply
    2. Сергей

      Ну с 30% понятно откуда она берется. А вот почему 9 % берет, а не не какое то другое число?

      Reply
    3. Sergey Olontsev

      Это как и 30% некая константа, которая зашита в оптимизатор. Но только 30% – это если ограничиваете выборку предикатом с одной стороны, а 9% – это когда указываете некий интервал.

      Я тут еще некоторые моменты с константами раскопал, думаю в ближайшее время опубликую заметку.

      Reply
    4. сашаневаша

      а есть ли у вас видео по олвэйс он или презентация, на сайте пдф не качается, а видео ужасного качества и ничего не видно, embrioz@bk,ru, спасибо

      Reply
    5. Artur Petrosyan

      Доброго дня вам. Меня очень понравился ваша статья. Оно очень детально обсуждает change tracking. У меня вопрос такой – как можно синхронизировать SQL Database (файл mdf) с SQL Sever, так как это делается с помщью чанге тракинг?

      Reply
    6. Sergey Olontsev

      Не совсем понял вас. Вы имеете ввиду подключаемый файл mdf в своем проекте Visual Studio? Если да, то например на SQL Server вы можете вручную включить Change Tracking и использовать обычнее его команды, чтобы получать список изменений с сервера. Только придется всю синхронизацию вручную прописывать в коде. А вот если хотите обратную синхронизацию, то сходу сразу не скажу: насколько я помню, это в принципе обычная БД, которая подключаетсяотключается к локальному экземпляру. А вообще использование именно mdf файла в вашем проекте чем мотивировано?

      Reply
    7. Artur Petrosyan

      Спасибо за ответ. в моем проекте я использую Service-based Database из за Database Diagram, что бы прeдoвтартить добавление неправильних данных, то есть не связанных(relationship), а также предотвращение удаления связанных данных.

      Reply
    8. Sergey Olontsev

      Но тот же SQL Server Compact поддерживает Foreign Keys, но правда там нет диаграмм, хотя мне кажется это не повод делать выбор. Кстати, если уж вы не хотиет использовать Compact Edition, то почему бы на клиенте не реализовать связку SQL Express и ваше приложение, вместо подключаемой базы?

      Reply
    9. Artur Petrosyan

      Потому что есть много клиентов и один сервер. Кожди клиент должен работать offline а после работы синхронизировать данные с сервером.

      Reply
    10. Sergey Olontsev

      Все верно, на клиенте будет SQL Express и SQL Express будет синхронизовываться в обе стороны с основным сервером. Тогда легко сможете использовать change tracking.

      Reply
    11. Artur Petrosyan

      Давайте я поясну. Пишу программу “рабочее место кассира”. Ну вот, есть много касс(клиенты) которие свoи данные, например наменкалатура, палучают из сервера, а обратную синхронизацию отправляют только документы чеков, тоесть продажа. У каждого чека уникальный номер, чтобы на сервере не запутать с чеками из других касс. База виброна SQL Datatabase (Service-based database) о чем я прежне говорил. База данных содаётса и каждая касcа работает нармально в локальном. Остается синхронизировать данные. Change Tracking работает только с Compact SQL(sdf), а тyт нужно синхронизация с файлом mdf.

      Reply
    12. Sergey Olontsev

      Change Tracking работает с любой версией, только вот я не уверен, как заставить его работать с Serice-based database. Но т.к. она из себя представляет просто подключаему базу данных, то почему бы вместо нее не использовать SQL Express на клиенте (все равно на клиенте он должен быть установлен для работы service-based database). Далее можно организовать синхронизацию разными способами, в т.ч. и change tracking. Вот только использовать мастеры для его настройки не получится, придется написать процедуры для синхронизации самому и запускать это все во время соединения с главным сервером.

      Reply
    13. Artur Petrosyan

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

      using System;
      using System.Data;
      using System.Data.SqlClient;
      using Microsoft.Synchronization;
      using Microsoft.Synchronization.Data;
      using Microsoft.Synchronization.Data.SqlServer;

      namespace ExecuteExpressSync
      {
      public class PosSyncAgent
      {
      private SyncOperationStatistics _syncstat;
      private string[] _tablenames;

      private const string Serverconnstring = @”Data Source=ART-PCSQLEXPRESS;” +
      “Initial Catalog=POSDataBase;Persist ” +
      “Security Info=True;User ID=sa;Password=111″;

      private const string Clientconnstring = @”Data Source=.SQLEXPRESS;” +
      @”AttachDbFilename=C:UsersArtDesktopposdb.mdf;” +
      “Integrated Security=True;Connect Timeout=30;User Instance=True”;

      public PosSyncAgent()
      {
      _tablenames = new[]
      {
      ” Users; “,
      ” UserTypes; “,
      ” ProductBarcodes; “,
      ” ProductsList; “,
      ” Units; “,
      ” DiscountCard; “,
      ” CustomersList; “,
      ” CardTypes;”
      };
      }

      #region Public Properties
      public SyncOperationStatistics DownloadStat
      {
      get { return _syncstat; }
      }
      #endregion

      public void SetupDBSynchronization(bool includeserverside)
      {
      var serverConn = new SqlConnection(Serverconnstring);
      var clientConn = new SqlConnection(Clientconnstring);

      try
      {
      clientConn.Open();

      using (var cmd = clientConn.CreateCommand())
      {
      foreach (var t in _tablenames)
      {
      cmd.CommandText = “delete from” + t;
      cmd.ExecuteNonQuery();
      }
      }

      var productScope = new DbSyncScopeDescription(“TableForUploads”);
      productScope.Tables.Add(SqlSyncDescriptionBuilder.GetDescriptionForTable(“dbo.UserTypes”, serverConn));
      productScope.Tables.Add(SqlSyncDescriptionBuilder.GetDescriptionForTable(“dbo.Users”, serverConn));
      productScope.Tables.Add(SqlSyncDescriptionBuilder.GetDescriptionForTable(“dbo.Units”, serverConn));
      productScope.Tables.Add(SqlSyncDescriptionBuilder.GetDescriptionForTable(“dbo.ProductsList”, serverConn));
      productScope.Tables.Add(SqlSyncDescriptionBuilder.GetDescriptionForTable(“dbo.ProductBarcodes”, serverConn));
      productScope.Tables.Add(SqlSyncDescriptionBuilder.GetDescriptionForTable(“dbo.CardTypes”, serverConn));
      productScope.Tables.Add(SqlSyncDescriptionBuilder.GetDescriptionForTable(“dbo.CustomersList”, serverConn));
      productScope.Tables.Add(SqlSyncDescriptionBuilder.GetDescriptionForTable(“dbo.DiscountCard”, serverConn));
      if (includeserverside)
      {
      var serverProvision = new SqlSyncScopeProvisioning(serverConn, productScope);

      if (!serverProvision.ScopeExists(“TableForUploads”))
      serverProvision.Apply();
      }

      var clientProvision = new SqlSyncScopeProvisioning(clientConn, productScope);

      if (!clientProvision.ScopeExists(“TableForUploads”))
      clientProvision.Apply();

      productScope = new DbSyncScopeDescription(“TableForDownloads”);
      productScope.Tables.Add(SqlSyncDescriptionBuilder.GetDescriptionForTable(“dbo.InvoiceHeader”, serverConn));
      productScope.Tables.Add(SqlSyncDescriptionBuilder.GetDescriptionForTable(“dbo.InvoiceData”, serverConn));

      if (includeserverside)
      {
      var serverProvision = new SqlSyncScopeProvisioning(serverConn, productScope);

      if (!serverProvision.ScopeExists(“TableForDownloads”))
      serverProvision.Apply();
      }

      clientProvision = new SqlSyncScopeProvisioning(clientConn, productScope);

      if (!clientProvision.ScopeExists(“TableForDownloads”))
      clientProvision.Apply();
      }
      catch (Exception ex)
      {
      throw new Exception(“Synchronization configuration error. ” + ex.Message);
      }
      finally
      {
      serverConn.Close();
      serverConn.Dispose();
      clientConn.Close();
      clientConn.Dispose();
      }
      }

      public void DownloadData()
      {
      if (!TableExists(“ProductsList_tracking”))
      {
      throw new Exception(“Database synchronization not created.”);
      }

      var serverConn = new SqlConnection(Serverconnstring);
      var clientConn = new SqlConnection(Clientconnstring);

      try
      {
      var syncOrchestrator = new SyncOrchestrator();
      var serverProvider = new SqlSyncProvider(“TableForUploads”, serverConn);
      var clientProvider = new SqlSyncProvider(“TableForUploads”, clientConn);
      syncOrchestrator.LocalProvider = serverProvider;
      syncOrchestrator.RemoteProvider = clientProvider;
      syncOrchestrator.Direction = SyncDirectionOrder.Upload;
      _syncstat = syncOrchestrator.Synchronize();
      }
      catch (Exception ex)
      {
      throw new Exception(“Database synchronization error. ” + ex.Message);
      }
      finally
      {
      serverConn.Close();
      serverConn.Dispose();
      clientConn.Close();
      clientConn.Dispose();
      }
      }

      public void UploadData()
      {
      if (!TableExists(“InvoiceData_tracking”))
      {
      throw new Exception(“Database synchronization not created.”);
      }

      var serverConn = new SqlConnection(Serverconnstring);
      var clientConn = new SqlConnection(Clientconnstring);

      try
      {
      var syncOrchestrator = new SyncOrchestrator();
      var serverProvider = new SqlSyncProvider(“TableForDownloads”, serverConn);
      var clientProvider = new SqlSyncProvider(“TableForDownloads”, clientConn);
      syncOrchestrator.LocalProvider = serverProvider;
      syncOrchestrator.RemoteProvider = clientProvider;
      syncOrchestrator.Direction = SyncDirectionOrder.DownloadAndUpload;
      _syncstat = syncOrchestrator.Synchronize();
      }
      catch (Exception ex)
      {
      throw new Exception(“Database synchronization error. ” + ex.Message);
      }
      finally
      {
      serverConn.Close();
      serverConn.Dispose();
      clientConn.Close();
      clientConn.Dispose();
      }
      }

      public void Deprovision(bool includeserverside)
      {
      var serverConn = new SqlConnection(Serverconnstring);
      var clientConn = new SqlConnection(Clientconnstring);

      try
      {
      clientConn.Open();

      using (var cmd = clientConn.CreateCommand())
      {
      foreach (var t in _tablenames)
      {
      cmd.CommandText = “delete from” + t;
      cmd.ExecuteNonQuery();
      }
      }

      if (!TableExists(“ProductsList_tracking”))
      {
      return;
      }

      var serverSqlDepro = new SqlSyncScopeDeprovisioning(serverConn);
      var clientSqlDepro = new SqlSyncScopeDeprovisioning(clientConn);

      if (includeserverside)
      {
      serverSqlDepro.DeprovisionScope(“TableForUploads”);
      serverSqlDepro.DeprovisionStore();
      }

      clientSqlDepro.DeprovisionScope(“TableForUploads”);
      clientSqlDepro.DeprovisionStore();

      if (TableExists(“InvoiceData_tracking”))
      {
      if (includeserverside)
      {
      serverSqlDepro.DeprovisionScope(“TableForDownloads”);
      serverSqlDepro.DeprovisionStore();
      }

      clientSqlDepro.DeprovisionScope(“TableForDownloads”);
      clientSqlDepro.DeprovisionStore();
      }
      }
      catch (Exception ex)
      {
      throw new Exception(“Deprovision error. ” + ex.Message);
      }
      finally
      {
      serverConn.Close();
      serverConn.Dispose();
      clientConn.Close();
      clientConn.Dispose();
      }
      }

      public string [] TablesRowCounts()
      {
      var clientConn = new SqlConnection(Clientconnstring);
      var tablenames = new string[_tablenames.Length];

      try
      {
      clientConn.Open();

      using (var cmd = clientConn.CreateCommand())
      {
      for (int i = 0; i < _tablenames.Length; i++)
      {
      cmd.CommandText = "select count(*) from" + _tablenames[i];

      using (var sqlrdr = cmd.ExecuteReader())
      {
      if (sqlrdr.Read())
      {
      tablenames[i] = _tablenames[i] + "t : " + sqlrdr.GetInt32(0);
      }
      }
      }
      }
      }
      catch (Exception ex)
      {
      throw new Exception("Tables data getting error. " + ex.Message);
      }
      finally
      {
      clientConn.Close();
      clientConn.Dispose();
      }

      return tablenames;
      }

      public bool TableExists(string tablename)
      {
      var clientConn = new SqlConnection(Clientconnstring);

      try
      {
      using (var command = new SqlCommand("Select * from " + tablename, clientConn))
      {
      command.CommandType = CommandType.Text;
      clientConn.Open();
      command.ExecuteNonQuery();
      return true;
      }
      }
      catch{}
      finally
      {
      clientConn.Close();
      clientConn.Dispose();
      }

      return false;
      }
      }
      }

      Reply
    14. Sergey Olontsev

      Хорошая штука, у меня только положительные впечатления. Не получилось только заставить по умолчанию по F1 вызываться, хотя судя по настройкам должен.

      Reply
    15. Дмитрий

      Сергей, как с вами можно связаться или как можно задать вопрос по планировщику 2008?

      Reply
    16. Александр Сигачёв

      Было бы здорово увидеть заметки об Extended Events

      Reply
        1. Александр Сигачёв

          Прочитал другие посты блога (очень интересно, кстати, спасибо) и вдруг понял, что все в этом мире связаны. Об этом блоге я узнал посмотрев записи докладов с MS DevCon. В прошлом году Дмитрий Костылев звал меня в Лабораторию Касперского на собеседование (увы, тогда я не прошёл), а потом я решал на собеседовании с Романом Дорошенко в НИКС интересные тестовые задания по БД – видимо, твоего авторства (правда, не пошёл к ним работать), и сейчас работаю в бизнес-центре на Вятской, где работал Дима до ухода к Касперскому. И почему только я раньше ничего не слышал об активности sql usergroup в Москве.

          Reply
          1. Sergey Olontsev

            Да уж. 🙂 Мир действительно очень тесен, не ожидал. Кстати, в ближайшее время планируется несколько встреч User Group, буду делать анонсы в блоге.

            Reply
    17. Pingback: Генерация скриптов для создания и удаления объектов SQL Server и с помощью Powershell | Олонцев Сергей

    18. Alexey

      Сергей, а есть материал(статья, видео и проч), которые вы порекомендовали бы по теме правильного написания CLR Table-valued functions?

      Reply
        1. Alexey

          Парсинг строк из таблицы с большим текстовом полем в другую таблицу в структурированном виде.

          Reply
          1. Sergey Olontsev

            А это разовая операция планируется или на регулярной основе? Насчет применения SSIS не думали для этого?

            Reply
            1. Alexey

              Регулярная. Script Transform в смысле? Ну в принципе тоже вариант.

            2. Sergey Olontsev

              Мне тоже кажется, что это быстрее будет и правильнее. Плюс этого метода в том, что он будет выполняться вне процесса SQL Server и его в будущем можно будет даже вынести на отдельный сервер, если будет большой поток данных для преобразования. Сможете легко масштабировать нагрузку. Потому что все методы оптимизации CLR функций, что я видел, заключались в оптимизации непосредственно C# или VB.NET кода, вызывались те или иные методы в зависимости от их производительности. Это очень тонкий тюнинг. А с ETL все гораздо проще. 🙂

    19. Alexey

      Сергей, спасибо за статью. Интересно было понять, будет ли данная система полезна для хранилища для отчётности (SSRS)? Я так понял что пока MS об этом не писали.

      Reply
      1. Sergey Olontsev

        Для хранилищ они ее не позиционируют, что собственно ожидаемо. На хранилищах в основном присутствует нагрузка – последовательное чтение. А последовательно считать на максимальной скорости можно и с обычной дисковой подсистемы. Ну и в хранилищах обычно данных очень много, поэтому их и кэшировать не имеет смысла – все равно все не влезет. Для отчетов SSRS кстати отлично можно использовать их встроенное кэширование и предварительный расчет – у меня было много таких реализаций. Ночью, например, заливка новой порции данных, трансформация и т.п., а потом SSRS обновляет отчеты, и к утру все сделано и мгновенно открывается.

        Reply
        1. Alexey

          Все новинки, кроме пожалуй columnstore clustered индекса для OLTP, даже скучно как-то : ) Насчёт кэширования SSRS не очень понял, там можно расписание настроить, когда отчёт будет кэшироваться или как?

          Reply
          1. Sergey Olontsev

            Columnstore это уже немало. 🙂 А для отчётов да, можно указать расписание, когда отчёты будут формироваться и настройки кэширования. Тут долго расписывать нюансы, но однозначно стоит посмотреть на эти настройки. Для тяжёлых и редко обновляемых отчётов самое то.

            Reply
            1. Alexey

              Сергей, а если в таблице Clustered Columnstore Index, к ней можно создать B-tree non-clustered index или нет? Я всё никак не доберусь проверить)

            2. Sergey Olontsev

              Нормально, там же совершенно по другому рганизовано хранение. Если рассматривать каждый индекс как отдельную физическую структуру – то ничего не мешает создать 2 копии таблицы – одна с columnstore, а вторую обычную урезанную и создать кластеризованный rowstore индекс. Физически будет одинаково, только если это действительно нужно и дает преимущество. 🙂 Вообще про columnstore в 2014 надо тоже будет серию статей готовить.

            3. Alexey

              Копия таблицы это слишком жирно) Получается либо по старому (non-clustered columnstore index), либо секционировать по годам (например) и сделать clustered columnstore index в случае, если основной фильтр будет эта дата.

            4. Sergey Olontsev

              Я к тому, что любой индекс это фактически копия части данных. Ну а так надо смотреть, что выгоднее будет в итоге учитывая все факторы.

    20. ya.a

      Сергей, отличная статья. Но в ней упущен один момент, как собственно понять что эта проблема есть и нужно работать над её решением. Исправляю сей недочёт. Для того что бы понять что у вас некоторые процессоры не используются на всю катушку (спят) нужно установить счетчик “Processor: %Processor Time)” на сутки и посмотреть равномерно ли распределяется нагрузка на процессоры с утра. Если вы увидите что при наступлении нагрузки (как правило с утра) она не равномерно распределена по всем CPU, то скорее всего ваши процессоры после ночного сна, ещё не успели проснуться и в этом виноват режим “Balanced”, попробуйте поставить на “High Perfomance” и проверьте считчики повторно. Примечание: если у вас OLTP система (MAXDOP=1), а не OLAP, то возможно что часть процессоров спит, так как на них нет нагрузки.

      Reply
      1. Sergey Olontsev

        Отличный комментарий. В свою очередь поделюсь еще информацией: позже я проводил тесты на IBM BladeCenter и там вообще не играло никакой роли, как были установлены параметры – сама система управляла энергопитанием. И время выполнения тестового запроса там сильно колебалось, в то время как на Supermicro оно было стабильным. Я вообще склоняюсь к факту, что энергопотребление в High Performance надо ставить сразу и без всяких дополнительных тестов. Идеальный вариант – создать OU на уровне AD, включить туда все MS SQL сервера в организации и повесить на OU доменную политику, которая сама рулит уже настройками (и не только энергопотребления).

        Reply
        1. ya.a

          Microsoft в рамках программы Microsoft RAS (Premier Support) советует ставить в High Perfomance. 🙂
          Основы телепатии изучили видимо ))

          Reply
          1. Sergey Olontsev

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

            Reply
    21. Дмитрий

      Сергей, укажите пожалуйста характеристики дисков и памяти для полноты картины.

      Reply
      1. Sergey Olontsev

        Тесты проводились на виртуальной машине, которая была расположена на обычной рабочей машине с Core i7 + SSD. Виртуалке было выделено 4 Гб памяти, но в зависимости от теста для SQL Server размер ограничивался. Там где нужно в тесте было задействовать HDD – я использовал обычный диск на 7200 оборотов – один, но т.к. не было конкурентной нагрузки, то не должно появиться разницы, сколько дисков будет, надо будет только учитывать кэш контроллеров или хранилища. А вот если взять диск на 15000 оборотов, то результаты потенциально могли быть в 1.5-2 раза лучше у тестов с использованием HDD. Я нисколько не претендую на какую-то особую точность в результатах, но мне было интересно провести более-менее реальные тесты и посмотреть. На реальном сервере результаты будут другими, т.к. придется учитывать изменение данных, конкуретную загрузку, зависимость запросов не только от производительности диска, но и процессоров и т.п.

        Reply
        1. Дмитрий

          Спасибо. Больше всего интересно, какие IOPS-ы у SSD? Лучше – сразу модель SSD. Мне кажется, эти значения могут оказать серьезное влияние на тесты с SSD.

          Reply
          1. Sergey Olontsev

            SSD – Corsair Neutron GTX. Если смотреть на то, что он может, то получаются такие результаты: случайное чтение 8кб блоками с очередью 1 – чуть больше 9000 IOPs, а случайная запись 1кб блоками с очередью 1 – почти 18000 IOPs. Эти показатели здесь, пожалуй, наиболее показательны.

            Reply
    22. Олег

      День добрый. Решил использовать Change Tracking в своем проекте, но столкнулся с проблемкой в Visual Studio 2012 нет такого шаблона. Возник вопрос, почему его убрали, и может появилось что-то новое ему на замену?

      Reply
    23. Артур Терегулов

      А почему четвертый быстрее пятого? о_О
      Часть BPE все же в оперативной памяти?
      Как я понимаю стандартный движок SQL без BPE не умеет держать части индекса в оперативной памяти, только целиком?

      Reply
      1. Sergey Olontsev

        Стандартный движок кэширует индексы по страницам, так что спокойно может находится в памяти только часть индекса. Здесь видимо играет роль то, что при чтении с диска Buffer Manager сначала выделяет Buf в памяти, заносит в него страницу и т.п. А если данные уже в BPE, то этой дополнительной нагрузки нет, поэтому и получилось быстрее. Опять же – это мое предположение.

        Reply
      1. Sergey Olontsev

        Артур, такой объем просто влезал. Смотреть можно через системное представление sys.dm_os_buffer_descriptors

        Reply
    24. Alexey

      Сергей, спасибо, всё прошло отлично : ) А будет рассылка с материалами докладов (презентации)?

      Reply
    25. Kostya Sviridov

      Для расчета stdev требуется чтение данных два раза?

      Reply
    26. ruzerone(Sergey)

      Есть пример как в оракле сделать то же самое?

      Reply
    27. Alexander

      кажется, в начале перепутаны местами формулы

      Reply
      1. Alexandr Tarlovsky

        Да, Вы правы! Только не сами формулы, а их sql-названия

        Reply
    28. Sergey

      Прочитал на”Харбаре” статью о Вашем замечательном офисе, но вдруг подумалось, – сколько времени эти молодые и успешные менеджеры тратят на дорогу по Московским пробкам и ещё в поисках места для парковки в соседних дворах?

      Подскажите пожалуйста их администраторам или во внутренней сети, что есть решение этой проблемы: http://www.kvadroom.ru/flat_arenda/object_80796735.html

      Reply
    29. Гость

      Добрый день! А есть ли запись этого семинара ? Или записей с этого мероприятия не существует ?

      Reply
      1. Sergey Olontsev

        Здравствуйте. В данный момент запись на встречах User Group не делается в принципе, т.к. планируется, что это больше мероприятия для неформальной встречи и общения участников. Обычно время доклада жестко не лимитируется, никто никуда не торопится.

        Reply
        1. Гость

          Ясно, спасибо. Очень обидно. Может что то подобное есть у других докладчиков ? Я про “Диагностика проблем в SQL Server, практический подход”.

          Reply
          1. Sergey Olontsev

            Сходу не скажу, есть ли что-то в этом же духе, кратко и в одном докладе. Стоит поискать на techdays.ru. У англоязычных спикеров можно поискать на YouTube.

            Reply
            1. Гость

              Спасибо! Поищу. Но к сожалению, пока не могу в английский.

    30. Semcho

      Насчёт сокращения циклов релизов не согласен. 2008R2 вышла 21 апреля 2010, 2012 – 6 марта, 2014 – 1 апреля. Так что примерно одинаково.

      Reply
      1. Sergey Olontsev

        Да, что-то я 2008R2 не учел, но если считать его больше как BI-релиз, т.к. по сути изменений там значимых в движке не было (сервис паками они потом практически невилировались полностью), то тенденция есть. Момент спорный, согласен. Смотря как считать. ))

        Reply
    31. Сергей

      Сергей, а такая ситуация на всех версиях SQL Server-а? На какой версии вы проводили исследование?

      Reply
      1. Sergey Olontsev

        Тестировал на 2014, т.к. тестировать под все версии не представляется возможным. Но я думаю, что на остальных будет также. Если вдруг у вас получатся другие результаты, сообщите мне. Будет крайне интересно.

        Reply
        1. Artem Pavlov

          Случайно наткнулся на стать, признаться, глаза закровоточили от “решения в лоб”

          StringToWords
          (
          @String varchar(MAX)
          , @Separator varchar(20)
          )
          RETURNS TABLE
          AS
          RETURN
          (
          WITH A AS
          (

          SELECT
          Word = LEFT(
          @String
          , CASE
          WHEN CHARINDEX (@Separator, @String) > 0 THEN CHARINDEX (@Separator, @String) – 1
          ELSE DATALENGTH(@String)
          END
          )

          , StartPos = CHARINDEX (@Separator, @String) + DATALENGTH(@Separator)
          , EndPos = CHARINDEX (@Separator, @String, CHARINDEX (@Separator, @String) + DATALENGTH(@Separator) )
          , Str = @String
          , Chk = CAST(1 AS bigint)
          , SepLen = DATALENGTH(@Separator)
          , RN = 1
          , CharFlag = CHARINDEX (@Separator, @String)
          UNION ALL
          SELECT
          Word = SUBSTRING(
          @String, A.StartPos, CASE
          WHEN A.EndPos – A.StartPos >= 0 THEN A.EndPos – A.StartPos
          ELSE DATALENGTH(@String)
          END
          )
          , StartPos = A.EndPos + DATALENGTH(@Separator)
          , EndPos = CHARINDEX (@Separator, @String, A.EndPos + DATALENGTH(@Separator) )
          , Str = @String
          , Chk = CAST(
          CASE
          WHEN A.EndPos – A.StartPos >= 0 THEN A.EndPos – A.StartPos
          ELSE DATALENGTH(@String)
          END AS bigint
          )
          , SepLen = DATALENGTH(@Separator)
          , RN = RN + 1
          , CharFlag = A.CharFlag
          FROM
          A
          WHERE
          A.CharFlag > 0
          AND A.Chk DATALENGTH(@String)

          )
          SELECT Word = LTRIM(RTRIM(Word)), RN FROM A

          )
          GO

          Reply
    32. Pingback: SQL Server 2016: Database Scoped Configuration | Олонцев Сергей

    33. Александр Семаков

      >>По умолчанию инсталлятор руководствуется следующей формулой: минимум из 2х значений, количество ядер на вашей системе и 8.
      Ядер физических или виртуальных?

      Reply
    34. Александр Семаков

      Еще вопрос
      >>Создавать файлов больше, чем у вас ядер в системе, не будет иметь
      практического смыла, ввиду того, что одновременно с tempdb не будет
      работать больше сессий, чем у вас ядер в системе.

      Каждое ядро работает со своим файлом? Или как повезет?

      Reply
      1. Sergey Olontsev

        А это не так важно на самом деле. Важно лишь то, есть ли у вас задержки при работе с tempdb в виде latch’ей или задержек по IO. Если есть, надо разбираться, почему они возникают.

        Reply
        1. Александр Семаков

          >>А это не так важно на самом деле
          То есть если есть 64 ядерный сервер, соответственно 64 сессии и все они пишут в один файл tempdb, хотя я их создам ххх.
          >>надо разбираться, почему они возникают.
          мне кажется в этом случае совсем понятно ПОЧЕМУ

          А если они будут писать каждая сессия в свой файл – то будет же лучше.
          Вот мне интересно как работает этот механизм

          Reply
          1. Sergey Olontsev

            Во-первых, будет зависеть, сколько всего активных сессий на сервере, и сколько из них пишут в tempdb. На то, как их SQL Server раскидает, вы повлиять все равно не сможете. А вот файлов стоит добавлять до тех пор, пока contention не исчезнет. Слишком много их тоже создавать не имеет особого смысла.

            Reply
    35. Тимур

      Можно для copy-paste программистов скрипт для переноса джобов?

      Reply
    36. Developer

      Главное достоинство JSON оценят веб-разработчики, так как XML проигрывает тут по всем статьям.
      Back-End серверу(например на C#) не потребуется делать преобразование из XML в JSON. Много мелких request от клиента, с постоянным парсингом на back-end и вы получите провал по производительности. Провал XML станет заметным, когда на ваш сервер в 1секунду производится более 1000 обращений от 1000 разных клиентов одновременно.
      Напротив, формат JSON из MS SQL 2016 позволяет напрямую передать его сразу во front-end, без каких-либо нагрузок на back-end.
      Приятно, что JSON в поле nvarchar(max) можно хранить до 2Гигабайт.
      Не думаю, что какому-то прийдет в голову тащить на веб-клиент, более 2Гиг JSON структуры. И главное сжатие JSON, намного будет быстрее чем использование его собрата BJSON.

      Reply
    37. Сергей

      Результаты опубликованного теста быстродействия на моем ноуте с 8 гигами и полностью отключенном свопе:

      100 000 итераций:

      data_type test_id path_expression returned_type elapsed_time_ms
      json 1 $[0].age int 9833
      json 2 $[2].”first name” varchar 10540
      json 3 $[2].skills[0] varchar 11597
      json u 1 $[0].age int 11943
      json u 2 $[2].”first name” varchar 13137
      json u 3 $[2].skills[0] varchar 14387
      xml 1 (/root/rec/age)[1] int 15710
      xml 2 (/root/rec/@first_name)[3] varchar 16766
      xml 3 /root[1]/rec[3]/skills[1]/skill[1] varchar 19090

      10 000 итераций:

      data_type test_id path_expression returned_type elapsed_time_ms
      json 1 $[0].age int 1787
      json 2 $[2].”first name” varchar 1003
      json 3 $[2].skills[0] varchar 1037
      json u 1 $[0].age int 970
      json u 2 $[2].”first name” varchar 963
      json u 3 $[2].skills[0] varchar 1057
      xml 1 (/root/rec/age)[1] int 1050
      xml 2 (/root/rec/@first_name)[3] varchar 1040
      xml 3 /root[1]/rec[3]/skills[1]/skill[1] varchar 1180

      Миллион итераций почему-то не выдерживал SSMS, а не сервер.

      Reply
    38. Peter

      Начиная с 2012 появилась опция for xml …, BINARY BASE64
      Т.е. вот такие конструкции – [почти] эквивалентны:
      Select Cast(N’plain_text’ as varbinary(max))
      for xml path(”), BINARY BASE64

      — Конвертируем значение переменной
      declare @value varbinary(max);
      set @value = cast(N’plain_text’ as varbinary(max));
      select cast(N” as xml).value(‘xs:base64Binary(sql:variable(“@value”))’, ‘varchar(max)’) as [encoded_value];

      Reply
    39. Egor Popov

      Привет. Не смог найти упоминаний об ограничении в 128 ГБ в других источниках. Возможно оно легаси или относится к редакции стандарт. Но я смог успешно добавить BPE файл 512 GB на сервере с 192 GB RAM 2014 Enterprise.

      “Максимальный поддерживаемый размер оперативной памяти 128 Гб, т.е. обладатели систем с большим размером памяти воспользоваться опцией не смогут. И это довольно неприятный момент, т.к. такой и больший объемы вполне доступны покупателям даже для серверов начального уровня.”

      Reply
    40. Pingback: Как измерить эксплуатационную надежность Big Data и зачем это нужно | Курсы Big Data, Hadoop, Kafka и Машинное обучение