Skip to content

Commit be7a674

Browse files
committed
Polybase Stats Rebuild Fix
Added functionality to correctly update statistics on external table. Per MS, they cannot be ALTERED. They must be dropped and recreated. Added variable @ExternalTables. Default is to REBUILD external table stats. Any additional values will be ignored.
1 parent af934ef commit be7a674

File tree

1 file changed

+69
-12
lines changed

1 file changed

+69
-12
lines changed

IndexOptimize.sql

Lines changed: 69 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ ALTER PROCEDURE [dbo].[IndexOptimize]
4343
@DatabasesInParallel nvarchar(max) = 'N',
4444
@ExecuteAsUser nvarchar(max) = NULL,
4545
@LogToTable nvarchar(max) = 'N',
46-
@Execute nvarchar(max) = 'Y'
46+
@Execute nvarchar(max) = 'Y',
47+
@ExternalTables nvarchar(max) = 'REBUILD'
4748

4849
AS
4950

@@ -157,6 +158,7 @@ BEGIN
157158
DECLARE @CurrentStatisticsSample int
158159
DECLARE @CurrentStatisticsResample nvarchar(max)
159160
DECLARE @CurrentDelay datetime
161+
DECLARE @CurrentIsExtenalTable bit
160162

161163
DECLARE @tmpDatabases TABLE (ID int IDENTITY,
162164
DatabaseName nvarchar(max),
@@ -204,6 +206,7 @@ BEGIN
204206
PartitionNumber int,
205207
PartitionCount int,
206208
StartPosition int,
209+
isExternalTable bit,
207210
[Order] int,
208211
Selected bit,
209212
Completed bit,
@@ -261,6 +264,11 @@ BEGIN
261264

262265
DECLARE @Version numeric(18,10) = CAST(LEFT(CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max)),CHARINDEX('.',CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max))) - 1) + '.' + REPLACE(RIGHT(CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max)), LEN(CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max))) - CHARINDEX('.',CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(max)))),'.','') AS numeric(18,10))
263266

267+
268+
DECLARE @tmpExternalTableColumnList TABLE (ColumnName nvarchar(max))
269+
DECLARE @ExternalTableColumnListCommand nvarchar(max) = N''
270+
271+
264272
IF @Version >= 14
265273
BEGIN
266274
SELECT @HostPlatform = host_platform
@@ -1550,7 +1558,7 @@ BEGIN
15501558
IF (EXISTS(SELECT * FROM @ActionsPreferred) OR @UpdateStatistics IS NOT NULL) AND (SYSDATETIME() < DATEADD(SECOND,@TimeLimit,@StartTime) OR @TimeLimit IS NULL)
15511559
BEGIN
15521560
SET @CurrentCommand = 'SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;'
1553-
+ ' SELECT SchemaID, SchemaName, ObjectID, ObjectName, ObjectType, IsMemoryOptimized, IndexID, IndexName, IndexType, AllowPageLocks, IsImageText, IsNewLOB, IsFileStream, IsColumnStore, IsComputed, IsTimestamp, OnReadOnlyFileGroup, ResumableIndexOperation, StatisticsID, StatisticsName, NoRecompute, IsIncremental, PartitionID, PartitionNumber, PartitionCount, [Order], Selected, Completed'
1561+
+ ' SELECT SchemaID, SchemaName, ObjectID, ObjectName, ObjectType, IsMemoryOptimized, IndexID, IndexName, IndexType, AllowPageLocks, IsImageText, IsNewLOB, IsFileStream, IsColumnStore, IsComputed, IsTimestamp, OnReadOnlyFileGroup, ResumableIndexOperation, StatisticsID, StatisticsName, NoRecompute, IsIncremental, PartitionID, PartitionNumber, PartitionCount, isExternalTable, [Order], Selected, Completed'
15541562
+ ' FROM ('
15551563

15561564
IF EXISTS(SELECT * FROM @ActionsPreferred) OR @UpdateStatistics IN('ALL','INDEX')
@@ -1592,14 +1600,21 @@ BEGIN
15921600
+ ', ' + CASE WHEN @PartitionLevel = 'Y' THEN 'partitions.partition_id AS PartitionID' WHEN @PartitionLevel = 'N' THEN 'NULL AS PartitionID' END
15931601
+ ', ' + CASE WHEN @PartitionLevel = 'Y' THEN 'partitions.partition_number AS PartitionNumber' WHEN @PartitionLevel = 'N' THEN 'NULL AS PartitionNumber' END
15941602
+ ', ' + CASE WHEN @PartitionLevel = 'Y' THEN 'IndexPartitions.partition_count AS PartitionCount' WHEN @PartitionLevel = 'N' THEN 'NULL AS PartitionCount' END
1595-
+ ', 0 AS [Order]'
1603+
+ ', ' + CASE WHEN @Version >= 13 THEN 'CASE WHEN external_tables.name IS NULL THEN 0 ELSE 1 END ' ELSE '0 ' END + 'as isExternalTable '
1604+
+ ', 0 AS [Order]'
15961605
+ ', 0 AS Selected'
15971606
+ ', 0 AS Completed'
15981607
+ ' FROM sys.indexes indexes'
15991608
+ ' INNER JOIN sys.objects objects ON indexes.[object_id] = objects.[object_id]'
16001609
+ ' INNER JOIN sys.schemas schemas ON objects.[schema_id] = schemas.[schema_id]'
16011610
+ ' LEFT OUTER JOIN sys.tables tables ON objects.[object_id] = tables.[object_id]'
16021611
+ ' LEFT OUTER JOIN sys.stats stats ON indexes.[object_id] = stats.[object_id] AND indexes.[index_id] = stats.[stats_id]'
1612+
1613+
IF @Version >= 13
1614+
BEGIN
1615+
SET @CurrentCommand += ' LEFT OUTER JOIN sys.external_tables external_tables ON objects.[object_id] = external_tables.[object_id] '
1616+
END
1617+
16031618
IF @PartitionLevel = 'Y'
16041619
BEGIN
16051620
SET @CurrentCommand = @CurrentCommand + ' LEFT OUTER JOIN sys.partitions partitions ON indexes.[object_id] = partitions.[object_id] AND indexes.index_id = partitions.index_id'
@@ -1643,6 +1658,7 @@ BEGIN
16431658
+ ', NULL AS PartitionID'
16441659
+ ', ' + CASE WHEN @PartitionLevelStatistics = 1 THEN 'dm_db_incremental_stats_properties.partition_number' ELSE 'NULL' END + ' AS PartitionNumber'
16451660
+ ', NULL AS PartitionCount'
1661+
+ ', ' + CASE WHEN @Version >= 13 THEN 'CASE WHEN external_tables.name IS NULL THEN 0 ELSE 1 END ' ELSE '0 ' END + 'as isExternalTable '
16461662
+ ', 0 AS [Order]'
16471663
+ ', 0 AS Selected'
16481664
+ ', 0 AS Completed'
@@ -1651,6 +1667,11 @@ BEGIN
16511667
+ ' INNER JOIN sys.schemas schemas ON objects.[schema_id] = schemas.[schema_id]'
16521668
+ ' LEFT OUTER JOIN sys.tables tables ON objects.[object_id] = tables.[object_id]'
16531669

1670+
IF @Version >= 13
1671+
BEGIN
1672+
SET @CurrentCommand += ' LEFT OUTER JOIN sys.external_tables external_tables ON objects.[object_id] = external_tables.[object_id] '
1673+
END
1674+
16541675
IF @PartitionLevelStatistics = 1
16551676
BEGIN
16561677
SET @CurrentCommand = @CurrentCommand + ' OUTER APPLY sys.dm_db_incremental_stats_properties(stats.object_id, stats.stats_id) dm_db_incremental_stats_properties'
@@ -1661,9 +1682,16 @@ BEGIN
16611682
+ ' AND NOT EXISTS(SELECT * FROM sys.indexes indexes WHERE indexes.[object_id] = stats.[object_id] AND indexes.index_id = stats.stats_id)'
16621683
END
16631684

1664-
SET @CurrentCommand = @CurrentCommand + ') IndexesStatistics'
1685+
SET @CurrentCommand = @CurrentCommand + ') IndexesStatistics '
1686+
SET @CurrentCommand = @CurrentCommand + 'WHERE 1=1 '
16651687

1666-
INSERT INTO @tmpIndexesStatistics (SchemaID, SchemaName, ObjectID, ObjectName, ObjectType, IsMemoryOptimized, IndexID, IndexName, IndexType, AllowPageLocks, IsImageText, IsNewLOB, IsFileStream, IsColumnStore, IsComputed, IsTimestamp, OnReadOnlyFileGroup, ResumableIndexOperation, StatisticsID, StatisticsName, [NoRecompute], IsIncremental, PartitionID, PartitionNumber, PartitionCount, [Order], Selected, Completed)
1688+
IF @ExternalTables <> 'REBUILD' OR (@ExternalTables = 'REBUILD' AND @Version < 13)
1689+
BEGIN
1690+
SET @CurrentCommand = @CurrentCommand + 'AND isExternalTable=0'
1691+
END
1692+
SELECT @CurrentCommand
1693+
1694+
INSERT INTO @tmpIndexesStatistics (SchemaID, SchemaName, ObjectID, ObjectName, ObjectType, IsMemoryOptimized, IndexID, IndexName, IndexType, AllowPageLocks, IsImageText, IsNewLOB, IsFileStream, IsColumnStore, IsComputed, IsTimestamp, OnReadOnlyFileGroup, ResumableIndexOperation, StatisticsID, StatisticsName, [NoRecompute], IsIncremental, PartitionID, PartitionNumber, PartitionCount, isExternalTable, [Order], Selected, Completed)
16671695
EXECUTE @CurrentDatabase_sp_executesql @stmt = @CurrentCommand
16681696
SET @Error = @@ERROR
16691697
IF @Error <> 0
@@ -1777,7 +1805,8 @@ BEGIN
17771805
@CurrentIsIncremental = IsIncremental,
17781806
@CurrentPartitionID = PartitionID,
17791807
@CurrentPartitionNumber = PartitionNumber,
1780-
@CurrentPartitionCount = PartitionCount
1808+
@CurrentPartitionCount = PartitionCount,
1809+
@CurrentIsExtenalTable = isExternalTable
17811810
FROM @tmpIndexesStatistics
17821811
WHERE Selected = 1
17831812
AND Completed = 0
@@ -2219,33 +2248,61 @@ BEGIN
22192248

22202249
SET @CurrentCommand = ''
22212250
IF @LockTimeout IS NOT NULL SET @CurrentCommand = 'SET LOCK_TIMEOUT ' + CAST(@LockTimeout * 1000 AS nvarchar) + '; '
2222-
SET @CurrentCommand += 'UPDATE STATISTICS ' + QUOTENAME(@CurrentSchemaName) + '.' + QUOTENAME(@CurrentObjectName) + ' ' + QUOTENAME(@CurrentStatisticsName)
22232251

2224-
IF @CurrentMaxDOP IS NOT NULL AND ((@Version >= 12.06024 AND @Version < 13) OR (@Version >= 13.05026 AND @Version < 14) OR @Version >= 14.030154)
2252+
IF @CurrentIsExtenalTable = 0
2253+
BEGIN
2254+
SET @CurrentCommand += 'UPDATE STATISTICS ' + QUOTENAME(@CurrentSchemaName) + '.' + QUOTENAME(@CurrentObjectName) + ' ' + QUOTENAME(@CurrentStatisticsName)
2255+
END
2256+
ELSE IF @CurrentIsExtenalTable = 1 AND @ExternalTables = 'REBUILD' AND @Version >= 13
2257+
BEGIN
2258+
2259+
SET @ExternalTableColumnListCommand = @ExternalTableColumnListCommand + 'SELECT columns.name '
2260+
+ 'FROM sys.external_tables as external_tables '
2261+
+ 'INNER JOIN SYS.external_table_columns AS external_table_columns ON external_tables.object_id = external_table_columns.object_id '
2262+
+ 'INNER JOIN sys.columns as columns on external_table_columns.column_id = columns.column_id '
2263+
+ 'AND external_tables.object_id = columns.object_id '
2264+
+ 'WHERE external_tables.name = ' + QUOTENAME(@CurrentObjectName, '''') + ' '
2265+
+ 'AND external_tables.schema_id = ' + CAST(@CurrentSchemaID AS varchar(100)) +';'
2266+
2267+
2268+
2269+
INSERT INTO @tmpExternalTableColumnList (ColumnName)
2270+
EXECUTE @CurrentDatabase_sp_executesql @stmt = @ExternalTableColumnListCommand
2271+
2272+
SET @CurrentCommand += 'DROP STATISTICS ' + QUOTENAME(@CurrentSchemaName) + '.' + QUOTENAME(@CurrentObjectName) + '.' + QUOTENAME(@CurrentStatisticsName) + ';'
2273+
SET @CurrentCommand += 'CREATE STATISTICS ' + QUOTENAME(@CurrentStatisticsName) + ' ON ' + QUOTENAME(@CurrentSchemaName) + '.' + QUOTENAME(@CurrentObjectName) + '('
2274+
SELECT @CurrentCommand += QUOTENAME(T.ColumnName) + ','
2275+
FROM @tmpExternalTableColumnList AS T
2276+
2277+
SET @CurrentCommand = LEFT(@CurrentCommand, LEN(@CurrentCommand)-1) + ') '
2278+
2279+
END
2280+
2281+
IF @CurrentMaxDOP IS NOT NULL AND ((@Version >= 12.06024 AND @Version < 13) OR (@Version >= 13.05026 AND @Version < 14) OR @Version >= 14.030154) AND @CurrentIsExtenalTable = 0
22252282
BEGIN
22262283
INSERT INTO @CurrentUpdateStatisticsWithClauseArguments (Argument)
22272284
SELECT 'MAXDOP = ' + CAST(@CurrentMaxDOP AS nvarchar)
22282285
END
22292286

2230-
IF @CurrentStatisticsSample = 100
2287+
IF @CurrentStatisticsSample = 100
22312288
BEGIN
22322289
INSERT INTO @CurrentUpdateStatisticsWithClauseArguments (Argument)
22332290
SELECT 'FULLSCAN'
22342291
END
22352292

2236-
IF @CurrentStatisticsSample IS NOT NULL AND @CurrentStatisticsSample <> 100
2293+
IF @CurrentStatisticsSample IS NOT NULL AND @CurrentStatisticsSample <> 100
22372294
BEGIN
22382295
INSERT INTO @CurrentUpdateStatisticsWithClauseArguments (Argument)
22392296
SELECT 'SAMPLE ' + CAST(@CurrentStatisticsSample AS nvarchar) + ' PERCENT'
22402297
END
22412298

2242-
IF @CurrentStatisticsResample = 'Y'
2299+
IF @CurrentStatisticsResample = 'Y' AND @CurrentIsExtenalTable = 0
22432300
BEGIN
22442301
INSERT INTO @CurrentUpdateStatisticsWithClauseArguments (Argument)
22452302
SELECT 'RESAMPLE'
22462303
END
22472304

2248-
IF @CurrentNoRecompute = 1
2305+
IF @CurrentNoRecompute = 1 AND @CurrentIsExtenalTable = 0
22492306
BEGIN
22502307
INSERT INTO @CurrentUpdateStatisticsWithClauseArguments (Argument)
22512308
SELECT 'NORECOMPUTE'

0 commit comments

Comments
 (0)