Ray D's blog


Не очень известный факт о кластерном индексе

Казалось бы все уже давно разжевано, однако об одном интересном факте мало кто знает --
при наличии кластерного индекса (уникального или неуникального), при создании неуникальных некластерных индексов,
ключ кластерного индекса будет не только на листовом уровне дерева, но и в промежуточных узлах.

Об этом подробно написала Kalen Delaney в своем блоге:
http://sqlblog.com/blogs/kalen_delaney/archive/2010/03/07/more-about-nonclustered-index-keys.aspx

Не пересказывая г-жу Дилани, отмечу только, что это приводит к интересному эффекту --
при наличии уникального кластерного индекса по полю X и неуникального некластерного
индекса по полю Y, для запроса вида
select ... where Y = @param1 and X = @param2
при использовании некластерного индекса, index seek будет по обоим полям -- Y, X, а не только по Y.
Если же этот индекс сделать уникальным, то, как и ожидается, ключ кластерного индекса будет только
на листовом уровне, и index seek будет только по Y.

Замечание msLex -- у Дилани написано, что это будет происходить только в том случае, если кластерный индекс уникальный. Тесты же показывают, что это происходит в любом случае.
добавлено: 03 авг 11 просмотры: 2765, комментарии: 15



SSAS parallel transactional incremental partitions processing

Dealing with huge amounts of data and SSAS? Have you ever tried parallel transactional incremental partitions processing? Odd enough but in this typical (at least to me and my team) scenario AMO generates invalid XMLA-script (because in this case all <Bindings> tags must be outside of the <Process> tag). As a result, you will get an exception.
However, it is easy to fix – let’s move all <Bindings> out of the <Process> command (I know, this code is far from perfect, feel free to refactor):
static string FixXMLAForParallel(string log, string SSASDatabaseName, string SSASDatabaseId, string DWHConnString)
        {
            string bindings = "<Bindings>";

            while (log.Contains("<Bindings>"))
            {
                int bindingsOpen = log.IndexOf("<Bindings>");
                int bindingsClose = log.IndexOf("</Bindings>");

                int bindOpen = log.IndexOf("<Binding>", bindingsOpen + "<Bindings>".Length);
                int bindClose = log.IndexOf("</Binding>");

                bindings += log.Substring(bindOpen, bindClose - bindOpen + "</Bindings>".Length);

                log = log.Remove(bindingsOpen, bindingsClose - bindingsOpen + "<Bindings>".Length + 1);
            }

            bindings += "</Bindings>";
            bindings += (@"<DataSource xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:type=""RelationalDataSource"">" +
                "<ID>" + SSASDatabaseId + "</ID>" +
                "<Name>" + SSASDatabaseName + "</Name>" +
                "<ConnectionString>" + DWHConnString + "</ConnectionString>" +
                "<ConnectionStringSecurity>Unchanged</ConnectionStringSecurity>" +
                "</DataSource>");

            log = log.Insert(log.IndexOf("</Parallel>") + "</Parallel>".Length, bindings);
            return log;
        }

And a usage example:
srv.CaptureXml = true;
ProcessDCPartitions(...);
srv.CaptureXml = false;
log = srv.ConcatenateCaptureLog(true, true);
results = srv.Execute(FixXMLAForParallel(log));
CheckProcessingError(results);
srv.CaptureLog.Clear();

        private void CheckProcessingError(XmlaResultCollection results)
        {
            string error = "";

            foreach (XmlaResult result in results)
            {
                foreach (XmlaMessage message in result.Messages)
                {
                    if (message is XmlaError)
                    {
                        error = error + message.Description + "\n";
                    }
                }
            }

            if (!string.IsNullOrEmpty(error))
            {
                throw new Exception(error);
            }

        }
scherbinin.blog.ru
добавлено: 10 июл 11 просмотры: 1820, комментарии: 3