Defrag and other stuff
This commit is contained in:
parent
5dad63c146
commit
3c5b1a1347
@ -9,13 +9,14 @@ namespace AsPartitionProcessing.SampleClient
|
|||||||
{
|
{
|
||||||
InitializeInline,
|
InitializeInline,
|
||||||
InitializeFromDatabase,
|
InitializeFromDatabase,
|
||||||
MergePartitions
|
MergePartitions,
|
||||||
|
DefragPartitionedTables
|
||||||
}
|
}
|
||||||
|
|
||||||
class Program
|
class Program
|
||||||
{
|
{
|
||||||
//Set sample execution mode here:
|
//Set sample execution mode here:
|
||||||
const SampleExecutionMode ExecutionMode = SampleExecutionMode.InitializeInline;
|
const SampleExecutionMode ExecutionMode = SampleExecutionMode.InitializeInline;
|
||||||
|
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
@ -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>
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user