예제 #1
0
    private void ScanIndexStart(object sender, DoWorkEventArgs e) {
      using (ConnectionList connectionList = new ConnectionList(Settings.ActiveHost)) {
        foreach (var database in Settings.ActiveHost.Databases) {
          List<Index> idx = new List<Index>();

          if (_workerScan.CancellationPending) {
            e.Cancel = true;
            return;
          }

          SqlConnection connection = connectionList.Get(database);
          if (connection == null) continue;

          Output.Current.Add($"Describe: {database}");
          Stopwatch opw = Stopwatch.StartNew();

          short retries = 0;
          while (true) {
            try {
              idx = QueryEngine.GetIndexes(connection);
              break;
            }
            catch (SqlException ex) {
              if (ex.Message.Contains("Incorrect syntax")) {
                Output.Current.Add($"Syntax error: {ex.Source}", ex.Message);
                XtraMessageBox.Show(ex.Message.Replace(". ", "." + Environment.NewLine), ex.Source, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
              }

              Output.Current.Add($"Pre-describe #{retries} failed: {database}. Rescan...", ex.Message);
              retries++;

              if (retries > 2 || !ex.Message.Contains("timeout")) {
                break;
              }
            }
          }

          opw.Stop();
          Output.Current.Add($"Pre-descibe: {(idx.Count(_ => _.Fragmentation != null))}. " +
                             $"Post-describe: {(idx.Count(_ => _.Fragmentation == null))}", null, opw.ElapsedMilliseconds);

          List<int> clid = new List<int>();

          foreach (Index index in idx.Where(_ => _.Fragmentation == null)
                                     .OrderBy(_ => _.ObjectId)
                                     .ThenBy(_ => _.IndexId)
                                     .ThenBy(_ => _.PartitionNumber)) {
            try {
              if (_workerScan.CancellationPending) {
                _scanIndexes.AddRange(idx);
                e.Cancel = true;
                return;
              }

              connection = connectionList.Get(database);
              if (connection == null) break;

              if (index.IndexType == IndexType.ColumnstoreClustered || index.IndexType == IndexType.ColumnstoreNonClustered) {
                if (!clid.Exists(_ => _ == index.ObjectId)) {
                  Output.Current.AddCaption(index.ToString());
                  opw = Stopwatch.StartNew();

                  QueryEngine.GetColumnstoreFragmentation(connection, index, idx);
                  clid.Add(index.ObjectId);

                  opw.Stop();
                  Output.Current.Add(index.ToString(), null, opw.ElapsedMilliseconds);
                }
              }
              else {
                Output.Current.AddCaption(index.ToString());
                opw = Stopwatch.StartNew();

                QueryEngine.GetIndexFragmentation(connection, index);

                opw.Stop();
                Output.Current.Add(index.ToString(), null, opw.ElapsedMilliseconds);
              }
            }
            catch (Exception ex) {
              Output.Current.Add($"Failed: {index}", ex.Message);
            }
          }

          _scanIndexes.AddRange(idx);
        }
      }
    }
예제 #2
0
        public int FixIndexes()
        {
            Output.Current.Add($"Host: {Settings.ActiveHost}");

            using (ConnectionList connectionList = new ConnectionList(Settings.ActiveHost)) {
                List <Index> scanIndex = new List <Index>();
                Stopwatch    watch;
                Stopwatch    totalWatch = Stopwatch.StartNew();

                foreach (var database in Settings.ActiveHost.Databases)
                {
                    List <Index> idx = new List <Index>();
                    watch = Stopwatch.StartNew();
                    SqlConnection connection = connectionList.Get(database);
                    if (connection == null)
                    {
                        continue;
                    }

                    Output.Current.Add(new string('-', 150));
                    Output.Current.Add($"Describe: {database}");

                    short retries = 0;
                    while (true)
                    {
                        try {
                            idx = QueryEngine.GetIndexes(connection);
                            break;
                        }
                        catch (SqlException ex) {
                            if (!ex.Message.Contains("timeout"))
                            {
                                throw new ArgumentException($"Error: {ex.Source} {ex.Message}");
                            }

                            retries++;
                            if (retries > 2)
                            {
                                break;
                            }
                        }
                    }

                    watch.Stop();
                    Output.Current.Add($"Pre-describe: {(idx.Count(_ => _.Fragmentation != null))}. " +
                                       $"Post-describe: {(idx.Count(_ => _.Fragmentation == null))}", null, watch.ElapsedMilliseconds);

                    List <int> clid = new List <int>();

                    foreach (Index index in idx.Where(_ => _.Fragmentation == null)
                             .OrderBy(_ => _.ObjectId)
                             .ThenBy(_ => _.IndexId)
                             .ThenBy(_ => _.PartitionNumber))
                    {
                        try {
                            connection = connectionList.Get(database);
                            if (connection == null)
                            {
                                break;
                            }

                            if (index.IndexType == IndexType.CLUSTERED_COLUMNSTORE || index.IndexType == IndexType.NONCLUSTERED_COLUMNSTORE)
                            {
                                if (!clid.Exists(_ => _ == index.ObjectId))
                                {
                                    watch = Stopwatch.StartNew();
                                    QueryEngine.GetColumnstoreFragmentation(connection, index, idx);
                                    clid.Add(index.ObjectId);
                                    watch.Stop();
                                    Output.Current.Add(index.ToString(), null, watch.ElapsedMilliseconds);
                                }
                            }
                            else
                            {
                                watch = Stopwatch.StartNew();
                                QueryEngine.GetIndexFragmentation(connection, index);
                                watch.Stop();
                                Output.Current.Add(index.ToString(), null, watch.ElapsedMilliseconds);
                            }
                        }
                        catch (Exception ex) {
                            Output.Current.Add($"Failed: {index}", ex.Message);
                        }
                    }

                    scanIndex.AddRange(idx);
                }

                var fixIndex = scanIndex.Where(_ => _.Fragmentation >= Settings.Options.FirstThreshold &&
                                               _.PagesCount >= Settings.Options.MinIndexSize.PageSize() &&
                                               _.PagesCount <= Settings.Options.MaxIndexSize.PageSize()).ToList();

                Output.Current.Add(new string('-', 150));
                Output.Current.Add($"Processed: {scanIndex.Count}. Fragmented: {fixIndex.Count}", null, totalWatch.ElapsedMilliseconds);

                if (fixIndex.Count > 0)
                {
                    totalWatch = Stopwatch.StartNew();
                    Output.Current.Add("Fix...");

                    foreach (Index ix in fixIndex)
                    {
                        if (ix.IndexType == IndexType.MISSING_INDEX)
                        {
                            ix.FixType = IndexOp.CREATE_INDEX;
                        }
                        else if (ix.Fragmentation < Settings.Options.SecondThreshold && ix.IsAllowReorganize)
                        {
                            ix.FixType = IndexOp.REORGANIZE;
                        }
                        else if (Settings.Options.Online && ix.IsAllowOnlineRebuild)
                        {
                            ix.FixType = IndexOp.REBUILD_ONLINE;
                        }
                        else
                        {
                            ix.FixType = IndexOp.REBUILD;
                        }

                        watch = Stopwatch.StartNew();
                        SqlConnection connection = connectionList.Get(ix.DatabaseName);
                        if (connection != null)
                        {
                            QueryEngine.FixIndex(connection, ix);
                        }
                        watch.Stop();

                        if (string.IsNullOrEmpty(ix.Error))
                        {
                            Output.Current.Add(ix.ToString(),
                                               $"Fragmentation: {ix.Fragmentation:n2}%. " +
                                               $"Size: {(Convert.ToDecimal(ix.PagesCountBefore) * 8).FormatSize()} -> {(Convert.ToDecimal(ix.PagesCount) * 8).FormatSize()}. " +
                                               $"Saved: {(Convert.ToDecimal(ix.PagesCountBefore - ix.PagesCount) * 8).FormatSize()}", watch.ElapsedMilliseconds);
                        }
                        else
                        {
                            Output.Current.Add(ix.ToString(), ix.Error);
                        }
                    }

                    Output.Current.Add(new string('-', 150));
                    Output.Current.Add($"Processed: {fixIndex.Count(_ => string.IsNullOrEmpty(_.Error))}. " +
                                       $"Errors: {fixIndex.Count(_ => !string.IsNullOrEmpty(_.Error))}", null, totalWatch.ElapsedMilliseconds);
                }
            }

            return(0);
        }