Defrag and other stuff

This commit is contained in:
christianwade 2016-12-19 00:43:00 -08:00
parent 5dad63c146
commit 3c5b1a1347
5 changed files with 167 additions and 8 deletions

View File

@ -9,7 +9,8 @@ namespace AsPartitionProcessing.SampleClient
{ {
InitializeInline, InitializeInline,
InitializeFromDatabase, InitializeFromDatabase,
MergePartitions MergePartitions,
DefragPartitionedTables
} }
class Program class Program
@ -46,6 +47,10 @@ namespace AsPartitionProcessing.SampleClient
{ {
PartitionProcessor.MergePartitions(modelConfig, LogMessage, "Internet Sales", Granularity.Yearly, "2012"); PartitionProcessor.MergePartitions(modelConfig, LogMessage, "Internet Sales", Granularity.Yearly, "2012");
} }
else if (ExecutionMode == SampleExecutionMode.DefragPartitionedTables)
{
PartitionProcessor.DefragPartitionedTables(modelConfig, LogMessage);
}
else else
{ {
PartitionProcessor.PerformProcessing(modelConfig, LogMessage); PartitionProcessor.PerformProcessing(modelConfig, LogMessage);
@ -57,8 +62,10 @@ namespace AsPartitionProcessing.SampleClient
Console.ForegroundColor = ConsoleColor.Red; Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(); Console.WriteLine();
Console.WriteLine(exc.Message, null); Console.WriteLine(exc.Message, null);
Console.WriteLine();
} }
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("Press any key to exit."); Console.WriteLine("Press any key to exit.");
Console.ReadKey(); Console.ReadKey();
} }
@ -164,7 +171,10 @@ namespace AsPartitionProcessing.SampleClient
} }
catch (Exception exc) catch (Exception exc)
{ {
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(exc.Message); Console.WriteLine(exc.Message);
Console.WriteLine();
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("Press any key to exit."); Console.WriteLine("Press any key to exit.");
Console.ReadKey(); Console.ReadKey();
Environment.Exit(0); //Avoid recursion if errored connecting to db Environment.Exit(0); //Avoid recursion if errored connecting to db

View File

@ -52,13 +52,12 @@ namespace AsPartitionProcessing
List<ModelConfiguration> modelConfigs = new List<ModelConfiguration>(); List<ModelConfiguration> modelConfigs = new List<ModelConfiguration>();
ModelConfiguration modelConfig = null; ModelConfiguration modelConfig = null;
int currentModelConfigurationID = -1; int currentModelConfigurationID = -1;
TableConfiguration tableConfig = null;
int currentTableConfigurationID = -1;
SqlDataReader reader = command.ExecuteReader(); SqlDataReader reader = command.ExecuteReader();
while (reader.Read()) while (reader.Read())
{ {
TableConfiguration tableConfig = null;
int currentTableConfigurationID = -1;
if (modelConfig == null || currentModelConfigurationID != Convert.ToInt32(reader["ModelConfigurationID"])) if (modelConfig == null || currentModelConfigurationID != Convert.ToInt32(reader["ModelConfigurationID"]))
{ {
modelConfig = new ModelConfiguration(); modelConfig = new ModelConfiguration();

View File

@ -86,13 +86,17 @@ namespace AsPartitionProcessing
} }
else else
{ {
//Partitioned table. Process based on partitioning configuration(s). //Validate multiple granularity ranges.
tableConfiguration.ValidatePartitioningConfigurations();
//Find template partition.
Partition templatePartition = table.Partitions.Find(tableConfiguration.AnalysisServicesTable); Partition templatePartition = table.Partitions.Find(tableConfiguration.AnalysisServicesTable);
if (templatePartition == null) if (templatePartition == null)
{ {
throw new InvalidOperationException($"Table {tableConfiguration.AnalysisServicesTable} does not contain a partition with the same name to act as the template partition."); throw new InvalidOperationException($"Table {tableConfiguration.AnalysisServicesTable} does not contain a partition with the same name to act as the template partition.");
} }
//Process based on partitioning configuration(s).
foreach (PartitioningConfiguration partitioningConfiguration in tableConfiguration.PartitioningConfigurations) foreach (PartitioningConfiguration partitioningConfiguration in tableConfiguration.PartitioningConfigurations)
{ {
LogMessage("", false); LogMessage("", false);
@ -207,6 +211,7 @@ namespace AsPartitionProcessing
{ {
LogMessage($"Inner exception message: {exc.InnerException.Message}", false); LogMessage($"Inner exception message: {exc.InnerException.Message}", false);
} }
LogMessage("", false);
} }
finally finally
{ {
@ -350,6 +355,79 @@ namespace AsPartitionProcessing
} }
} }
/// <summary>
/// Defragment all partitions tables in a tabular model based on configuration
/// </summary>
/// <param name="modelConfiguration">Configuration info for the model</param>
/// <param name="messageLogger">Pointer to logging method</param>
public static void DefragPartitionedTables(ModelConfiguration modelConfiguration, LogMessageDelegate messageLogger)
{
_modelConfiguration = modelConfiguration;
_messageLogger = messageLogger;
Server server = new Server();
try
{
Database database;
Connect(server, out database);
Console.ForegroundColor = ConsoleColor.White;
LogMessage($"Start: {DateTime.Now.ToString("hh:mm:ss tt")}", false);
LogMessage($"Server: {_modelConfiguration.AnalysisServicesServer}", false);
LogMessage($"Database: {_modelConfiguration.AnalysisServicesDatabase}", false);
Console.ForegroundColor = ConsoleColor.Yellow;
LogMessage("", false);
LogMessage($"Defrag partitioned tables in database {_modelConfiguration.AnalysisServicesDatabase}", false);
LogMessage(new String('-', _modelConfiguration.AnalysisServicesDatabase.Length + 38), false);
LogMessage("", false);
LogMessage("=>Actions & progress:", false);
foreach (TableConfiguration tableConfiguration in _modelConfiguration.TableConfigurations)
{
//Only interested in partitoned tables
if (tableConfiguration.PartitioningConfigurations.Count > 0)
{
Table table = database.Model.Tables.Find(tableConfiguration.AnalysisServicesTable);
if (table == null)
{
throw new Microsoft.AnalysisServices.ConnectionException($"Could not connect to table {tableConfiguration.AnalysisServicesTable}.");
}
LogMessage($"Defrag table {tableConfiguration.AnalysisServicesTable} ...", true);
table.RequestRefresh(RefreshType.Defragment);
database.Model.SaveChanges();
}
}
Console.ForegroundColor = ConsoleColor.White;
LogMessage("", false);
LogMessage("Finish: " + DateTime.Now.ToString("hh:mm:ss tt"), false);
}
catch (Exception exc)
{
Console.ForegroundColor = ConsoleColor.Red;
LogMessage("", false);
LogMessage($"Exception occurred: {DateTime.Now.ToString("hh:mm:ss tt")}", false);
LogMessage($"Exception message: {exc.Message}", false);
if (exc.InnerException != null)
{
LogMessage($"Inner exception message: {exc.InnerException.Message}", false);
}
LogMessage("", false);
}
finally
{
try
{
_modelConfiguration = null;
_messageLogger = null;
if (server != null) server.Disconnect();
}
catch { }
}
}
#endregion #endregion
#region Private Methods #region Private Methods

View File

@ -5,7 +5,7 @@ namespace AsPartitionProcessing
/// <summary> /// <summary>
/// Configuration information for partitioning of a table within an AS tabular model. /// Configuration information for partitioning of a table within an AS tabular model.
/// </summary> /// </summary>
public class PartitioningConfiguration public class PartitioningConfiguration : IComparable<PartitioningConfiguration>
{ {
/// <summary> /// <summary>
/// ID of the PartitioningConfiguration table. /// ID of the PartitioningConfiguration table.
@ -101,8 +101,8 @@ namespace AsPartitionProcessing
default: default:
break; break;
} }
} }
public int CompareTo(PartitioningConfiguration other) => string.Compare(this.LowerBoundary.ToString("yyyy-MM-dd"), other.LowerBoundary.ToString("yyyy-MM-dd"));
} }
/// <summary> /// <summary>

View File

@ -47,5 +47,77 @@ namespace AsPartitionProcessing
public TableConfiguration() public TableConfiguration()
{ {
} }
/// <summary>
/// Validate multiple granularities to ensure no overlapping ranges, etc.
/// </summary>
public void ValidatePartitioningConfigurations()
{
if (this.PartitioningConfigurations.Count > 1)
{
this.PartitioningConfigurations.Sort(); //Sorts by LowerBoundary value
DateTime previousUpperBoundary = DateTime.MinValue;
Granularity previousGranularity = Granularity.Daily;
bool foundDaily = false, foundMonthly = false, foundYearly = false;
foreach (PartitioningConfiguration partitioningConfiguration in this.PartitioningConfigurations)
{
#region Check don't have multiple partitioning configurations with same granularity
string multiSameGrainErrorMessage = $"Table {this.AnalysisServicesTable} contains multiple {{0}} partitioning configurations, which is not allowed.";
switch (partitioningConfiguration.Granularity)
{
case Granularity.Daily:
if (foundDaily)
{
throw new InvalidOperationException(string.Format(multiSameGrainErrorMessage, "daily"));
}
else
{
foundDaily = true;
}
break;
case Granularity.Monthly:
if (foundMonthly)
{
throw new InvalidOperationException(string.Format(multiSameGrainErrorMessage, "monthly"));
}
else
{
foundMonthly = true;
}
break;
case Granularity.Yearly:
if (foundYearly)
{
throw new InvalidOperationException(string.Format(multiSameGrainErrorMessage, "yearly"));
}
else
{
foundYearly = true;
}
break;
default:
break;
}
#endregion
#region Check don't have overlapping date ranges
if (partitioningConfiguration.LowerBoundary <= previousUpperBoundary)
{
throw new InvalidOperationException($"Table {this.AnalysisServicesTable} contains partitioning configurations with overlapping date ranges, which is not allowed. {previousGranularity.ToString()} upper boundary is {previousUpperBoundary.ToString("yyyy-MM-dd")}; {partitioningConfiguration.Granularity.ToString()} lower boundary is {partitioningConfiguration.LowerBoundary.ToString("yyyy-MM-dd")}.");
}
else
{
previousUpperBoundary = partitioningConfiguration.UpperBoundary;
previousGranularity = partitioningConfiguration.Granularity;
}
#endregion
}
}
}
} }
} }