2017-04-15 4 views
2

Dans Azure Data Warehouse, il est recommandé d'utiliser HASH pour les tables distribuées sur les champs que vous envisagez de JOIN et même potentiellement agréger. Il est également recommandé de créer des statistiques sur les champs que vous prévoyez d'utiliser. Disons que vous avez deux tables avec la même quantité d'enregistrements et de champs. Une table est hachée sur une clé très unique où l'autre est ROUND_ROBIN, où les données sont réparties de façon aléatoire entre les 60 bases de données.Les statistiques aident-elles les champs sur JOINS comme le hachage dans Azure Data Warehouse?

-- CustomerID is alphanumeric 
SELECT 
    [ProductID] 
    ,COUNT(DISTINCT [CustomerID]) AS [Unique Records] 
FROM [dbo].[FactTable] 
GROUP BY 
    [Product] 

Sur la table hachée, si vous regroupez sur la clé hachée, vous pouvez le voir est le retour des résultats dans 0,05 secondes. Sur la table ronde, avec la même agrégation, c'est 0,51 secondes. Lorsque vous appliquez des statistiques aux champs que vous agrégez, la table hachée retourne toujours dans 0.05 secondes. Pas de changement. Lorsque vous faites la même chose à la table round robin, les résultats reviennent à la même chose que le hashed dans les 0,05 secondes.

Note: 2000 DWU requête en cours d'exécution en ressources xlarge (allocation mémoire max)

Lors de l'examen de la distribution de la clé hachée, je l'ai trouvé 140 millions d'enregistrements sont stockés dans une distribution des 60 bases de données. 50 millions d'autres enregistrements sont distribués assez uniformément dans les 59 autres bases de données. Une valeur par défaut rend ma clé hachée pas un bon candidat pour un hachage. Ma question est la suivante: alors que la table ronde avec statistiques fonctionne très bien sur le même champ que je suis avec l'autre table, est-ce que les mêmes performances resteront quand j'utiliserai le round robin sur JOINS avec cette touche? Je ne l'ai pas encore testé complètement, mais je cherche la meilleure approche.

Les statistiques aident-elles sur les jointures? Certains des articles que j'ai lus disent qu'ils le font, mais voir si quelqu'un d'autre a des réponses plus solides sur l'approche lorsque l'on considère Round Robin sur une clé de distribution. Je n'ai pas vraiment de bons candidats qui ne causent pas de biais de données comme dans mon exemple ci-dessus avec les 140 millions.

+1

Si vous souhaitez que les réponses soient plus concrètes, il serait utile de publier le plan d'explication pour toutes les requêtes que vous avez testées. Mettez le mot 'EXPLAIN' devant la requête et exécutez-le, puis copiez le code XML dans votre question. – GregGalloway

+0

N'en a pas vraiment, mais inclus l'exemple SQL pour référence. C'est juste une requête de base SELECT COUNT (DISTINCT) GROUP BY. – Fastidious

+0

pouvez-vous en obtenir un? Je voudrais voir si les statistiques changent le plan d'explication ou si les différences de performance sont juste liées à la mise en cache. – GregGalloway

Répondre

1

Tout d'abord, dans la version actuelle de SQL Azure Data Warehouse, vous devez toujours créer des statistiques sur les colonnes que vous allez utiliser dans des jointures, etc. GROUP BY Ignorer les horaires que vous avez obtenus sans statistiques car ils ne sont pas pertinents. L'un des critères d'une bonne clé de hachage est distributes the data evenly. Si vous n'avez pas un bon candidat, alors ROUND_ROBIN est l'alternative. La chose à garder à l'esprit au sujet de ROUND_ROBIN est que vous obtenez toujours le mouvement de données, mais parfois c'est bien. Cela dépend vraiment de ce que sont vos requêtes clés. Mon conseil serait d'optimiser pour eux.

Pour les exemples que vous avez donnés, les performances sont si rapides que cela ne vaut vraiment pas la peine de passer trop de temps. Avez-vous des questions plus réalistes?

Azure SQL Data Warehouse est mis en cache, similaire à SQL Server, comme décrit here.J'ai simulé une plate-forme de test en utilisant l'exemple AdventureWorksDW disponible lorsque vous provisionnez un entrepôt depuis le portail, et j'ai trouvé que la table hachée était significativement améliorée (malgré un grand décalage) pour ces exemples mais votre kilométrage peut varier (YMMV):

-- 603,980,000 rows 
CREATE TABLE dbo.FactTable_rr 
WITH ( 
    DISTRIBUTION = ROUND_ROBIN, 
    CLUSTERED COLUMNSTORE INDEX 
) 
AS 
SELECT a.ProductKey AS [ProductID], a.CustomerKey AS [CustomerID] 
FROM [dbo].[FactInternetSales] a 
    CROSS JOIN (SELECT TOP 1000 1 FROM [dbo].[FactInternetSales]) b(c) 
    CROSS JOIN (SELECT TOP 10 1 FROM [dbo].[FactInternetSales]) c(c) 
GO 


CREATE STATISTICS st_dbo_FactTable_rr_ProductID ON dbo.FactTable_rr (ProductID) WITH FULLSCAN; 
CREATE STATISTICS st_dbo_FactTable_rr_CustomerID ON dbo.FactTable_rr (CustomerID) WITH FULLSCAN; 
GO 


CREATE TABLE dbo.FactTable_hh 
WITH ( 
    DISTRIBUTION = HASH([ProductID]), 
    CLUSTERED COLUMNSTORE INDEX 
) 
AS 
SELECT * 
FROM FactTable_rr 
GO 

CREATE STATISTICS st_dbo_FactTable_hh_ProductID ON dbo.FactTable_hh (ProductID) WITH FULLSCAN; 
CREATE STATISTICS st_dbo_FactTable_hh_CustomerID ON dbo.FactTable_hh (CustomerID) WITH FULLSCAN; 
GO 



-- Find data skew for a distributed table 
DBCC PDW_SHOWSPACEUSED('dbo.FactTable_rr'); 
DBCC PDW_SHOWSPACEUSED('dbo.FactTable_hh'); 
GO 


--EXPLAIN 
SELECT 
    [ProductID], 
    COUNT(DISTINCT [CustomerID]) AS [Unique Records] 
FROM [dbo].[FactTable_rr] 
GROUP BY [ProductID] 
OPTION (LABEL = 'rr'); 


--EXPLAIN 
SELECT 
    [ProductID], 
    COUNT(DISTINCT [CustomerID]) AS [Unique Records] 
FROM [dbo].[FactTable_hh] 
GROUP BY [ProductID] 
OPTION (LABEL = 'hh'); 


-- Summary 
SELECT [label], COUNT(*) records, CAST(AVG(total_elapsed_time)/1000. AS DECIMAL(10,2)) total_elapsed_time_s 
FROM sys.dm_pdw_exec_requests 
WHERE [label] IS NOT NULL 
    AND command Like 'select%' 
GROUP BY [label]; 

Mes résultats, avec une table de 600 millions de lignes:

My results

Si je regarde les deux EXPLIQUEZ plans pour les deux requêtes (rr, hh), je vois un plan beaucoup plus simple pour la table de hachage sans mouvement de données. Le plan 'rr' contient un opérateur SHUFFLE_MOVE qui redistribue une table distribuée.

+0

Mon problème est que même sur de simples requêtes, il est suspendu à un milliard de lignes. Les requêtes SImple qui se regroupent en exécutant DATEPART et GROUP BY sur des lignes hautement uniques afin d'éviter d'effectuer COUNT (DISTINCT) sur ces mêmes lignes hautement uniques prennent beaucoup de temps. – Fastidious

+0

Cela ressemble à un scénario complètement différent de celui que vous avez décrit (où la performance est inférieure à la seconde)? Si vous pouviez fournir le DDL, des exemples de données et des requêtes réelles que vous exécutez et les plans d'explication, alors quelqu'un pourra vous aider. Honnêtement le scénario que vous venez de décrire ressemble à une question distincte – wBob

+0

C'est fondamentalement la même requête, mais sur une table différente avec plus d'enregistrements. La seule différence est qu'il y a un filtre de plus basé sur un ensemble de données qui contient un milliard d'enregistrements dans ce filtre, où l'exemple de requête que je montre est basé sur un autre sous-ensemble de données qui est seulement 200 millions d'enregistrements que je divise en une autre table . Étant donné que je l'ai divisé, la requête a pu revenir en quelques secondes par rapport à plusieurs minutes. Mais oui, ça peut être une autre question. Pourquoi la même requête ne peut-elle pas fonctionner sur des données plus volumineuses? :) – Fastidious