Lors de la mise en place d’une évolution sur un cube que j’avais fait il y a un moment, j’en profite pour ajouter un peu de partitionnement étant donné que le cube avait bien grossi. Voulant aller vite, je crée 3 partitions, je déploie et paf, une erreur :
3240034361 : Erreurs dans le moteur de stockage OLAP : Les restrictions imposées sur un secteur de partition n’ont pas été respectées
(en anglais : Errors in the OLAP storage engine: The restrictions imposed on partition slice where violated)
Le problème vient de la propriété Slice de mes partitions que j’ai mis un peu hâtivement.
Explications en repartant du début…
Définir les partitions
Première chose à faire, définir les partitions. Pour cet article, je vais prendre la base Contoso (un AdventureWorks un peu plus épais) et je vais partitionner par Magasin (StoreKey).
En étudiant les données, je vois qu’elles ne sont pas distribuées également ; quelques magasins sortent du lot.
Je vais donc définir un schéma de partitionnement non linéaire en créant 7 partitions.
Je déploie, je process, tout va bien. Sauf qu’en testant, on peut voir que les partitions ne sont pas correctement utilisées dans les requêtes MDX.
Avec une requête sur un Magasin précis, on voit avec le Profiler que plusieurs partitions sont lues.
SELECT [Measures].[Sales Amount] ON 0 ,[Calendar].[Year].Children ON 1 FROM [Contoso] WHERE ([Stores].[Store].&[310])
Rappelons toutefois qu’il y a 2 avantages au partitionnement :
- Optimisation des requêtes (on vient d’en parler)
- Optimisation du Process en ne traitant que la “dernière” partition
Ce second point peut à lui seul justifier la mise en place de partitions. A ce propos, Microsoft recommande de partitionner à partir de 2 millions de lignes.
Propriété Slice
Si le moteur ne pointe pas directement sur la bonne partition, c’est parce que, dans mon partitionnement, je dois lui indiquer sur quel critère.
En SSAS multidim, cette clé de partitionnement s’appelle un Slice (traduit par “tranche” dans les outils en français). On trouve cette propriété Slice sur l’objet Partition.
Cette propriété attend une expression en MDX qui renvoie un Tuple ou un Set. Ainsi pour notre partitionnement par Magasin, on aura une instruction comme celle-ci :
{[Stores].[Store].&[199],[Stores].[Store].&[200]}
Etant donné que j’ai plus de 300 magasins sur 7 partitions, je pars sur un Range (avec un : entre mes bornes) :
{[Stores].[Store].&[201]:[Stores].[Store].&[305]}
Et pour la première et la dernière partition,
{null:[Stores].[Store].&[198]} {[Stores].[Store].&[311]:null}
En testant dans une requête MDX, cela fonctionne très bien.
SELECT [Measures].[Sales Amount] ON 0 ,{null:[Stores].[Store].&[199]} ON 1 FROM [Contoso]
Sauf que c’est ce Range qui est à l’origine de l’erreur au Processing !
Pourquoi ?
Au traitement, Analysis Services utilise ce que vous avez mis dans la propriété Slice dans une instruction StrToMember(“propriété slice”, CONSTRAINED). Et la fonction StrToMember, en mode CONSTRAINED, ne supporte pas les Range…
Quelques références sur les limitations de STRTOMEMBER :
- http://social.technet.microsoft.com/Forums/fr-FR/80f6a49d-3beb-4952-8bc6-75adff865b06/partition-slicing-issues-and-performance-urgent?forum=sqlanalysisservices&prof=required (seconde réponse de Greg Galloway)
- http://cwebbbi.wordpress.com/2006/01/17/the-strto-functions-and-constrained/
La solution ?
Elle est simple, il vous faut indiquer TOUS les membres de la partitions dans votre Set. Ou encore créer plus de partitions. C’est pourquoi la gestion des partitions est souvent automatisée (PowerShell avec AMO, SSIS), mais ça, ce sera pour un prochain article.
Pour conclure, une fois les slices correctement définis sur les partitions, ma requête MDX requête la bonne partition, et uniquement celle-ci.
AutoSlice
Si vous avez correctement suivi, vous avez dû remarquer qu’il y a un truc qui ne colle pas. J’ai 7 partitions et quand j’ai requêté sans les Slices définis, il n’a scanné que 4 partitions. Pourquoi ?
Tout simplement car Analysis Services essaye quand même de déduire le critère de partitionnement au moment du Processing. Dans ces métadonnées, il indique les valeurs min et max de chaque dimension.
C’est pour cela qu’il arrive à se débrouiller pour retrouver les partitions éligibles. Mais comme vous avez pu le voir, ce n’est pas parfait (principalement car il peut y avoir de l’overlap).
Pour creuser l’AutoSlice, je vous renvoie à l’article de Shabnam Watson : http://shabnamwatson.wordpress.com/2013/06/27/setting-the-slice-for-ssas-partitions/
–
Même sans l’argument Contrained, StrToMember n’accepte qu’un membre et donc pas d’intervalles.
Dans la partie « Pourquoi? », tu parles de STRTOSET, ou bien?
Y’en a 1 qui suit !! 🙂
Il y a bien une coquille, je parle de STRTOSET et non STRTOMEMBER
Merci, je vais corriger.