clement13.net
Photo d’origine : Disque dur éventré dont le plateau et les pièces mécaniques gisent en morceaux.
Description
Disque dur éventré dont le plateau et les pièces mécaniques gisent en morceaux.
Source
Stefan Bellini · page d’origine
Licence
CC0 Domaine public
Photo d’origine, non retouchée. L’arrière-plan en est une version stylisée par le site.

SQL Server en SaaS — difficultés et pièges

Vous saurez reconnaître les familles de pannes d'une chaîne Azure SQL → Power BI : performance (DirectQuery, DTU), mesure (élasticité), réseau, identité, limites du service, modèle, langue…

Guide≈ 21 min de lectureVérifié en partieContrôle partielLes faits principaux ont été contrôlés par recherche dans des sources citées. Les éléments ci-dessous restent à recontrôler avant de s’y fier.À recontrôler
  • Disponibilité du chargement minimalement journalisé sur Azure SQL Database non confirmée (remède reformulé prudemment).
  • Chiffres de pourcentage de réduction serverless et mémoire doublée à l'actualisation restent des ordres de grandeur non sourcés.
Rédaction assistée par IA ; sources citées en bas de page. Une erreur ? Signalez-la via le site clement13.net.
Lecture
En bref
  • Vous saurez reconnaître les familles de pannes d'une chaîne Azure SQL → Power BI : performance (DirectQuery, DTU), mesure (élasticité), réseau, identité, limites du service, modèle, langue, temps, sécurité, coût.
  • Vous disposerez d'un catalogue de 39 pièges avec symptôme, cause et remède, classés par famille, et d'un protocole de diagnostic en 6 étapes.
  • Vous saurez distinguer un problème de base, de modèle ou de service avant de toucher à quoi que ce soit.
  • Cadre : vue d'ensemble ; mécanismes : architecture ; IA de diagnostic : 08.
Sur cette page

Niveau : 🟢→🔴

Protocole de diagnostic#

🟢 Novice — Où chercher d'abord ?#

Quand « le rapport est lent » ou « l'actualisation a échoué », trois couches sont candidates. Ne changez rien avant d'avoir localisé la couche.

  1. Le rapport / le visuel — l'analyseur de performance de Power BI Desktop sépare le temps DAX, le temps de requête (DirectQuery) et le temps d'affichage.
  2. Le modèle — taille, cardinalité, relations, mesures lourdes (outils : DAX Studio, VertiPaq Analyzer).
  3. La source — Query Store, sys.dm_exec_requests, ressources (sys.dm_db_resource_stats).

🟡 Pratique — Les six étapes#

# Étape Question Outil
1 Reproduire Est-ce toujours, ou seulement à certaines heures/utilisateurs ? Journal d'actualisation, historique
2 Localiser Rapport, modèle, source, réseau, identité ? Analyseur de performance, journaux
3 Mesurer CPU, lectures logiques, attente dominante Query Store, sys.dm_exec_session_wait_stats
4 Comparer Qu'est-ce qui a changé (modèle, volume, niveau de service, plan) ? Historique Git, Query Store, journal d'activité
5 Corriger au bon endroit Source > modèle > rapport Voir catalogue
6 Verrouiller Test, alerte, documentation Matrice BI exploitation et supervision
💡 Astuce d'expert

Un incident sans changement identifiable est presque toujours dû à la croissance des données (volumétrie qui franchit un seuil : mémoire, limite de taille, plan différent) ou à une expiration (jeton, mot de passe, certificat, secret d'application).

Performance : DirectQuery, verrous, DTU#

🟡 Pratique — DirectQuery lent et verrous#

DirectQuery génère une ou plusieurs requêtes SQL par visuel, à chaque interaction (filtre, segment, survol détaillé). Une page de 10 visuels = 10 à 30 requêtes simultanées par utilisateur. Avec 100 utilisateurs, la base doit encaisser des milliers de requêtes par minute, avec des agrégations à la volée.

Mécanismes de lenteur :

  • Vues complexes en couche d'exposition : jointures multiples, fonctions scalaires, DISTINCT déguisés.
  • Prédicats non sargables produits par les mesures DAX (conversions de type, fonctions sur colonnes).
  • Absence de columnstore sur les gros faits ; rowstore + agrégats sur centaines de millions de lignes.
  • Verrous : les lectures concurrentes de DirectQuery se heurtent aux écritures de la consolidation. Sous isolation READ COMMITTED standard sur Azure SQL, les lectures utilisent par défaut le versionnement de lignes (READ_COMMITTED_SNAPSHOT activé par défaut sur Azure SQL Database), ce qui évite la plupart des blocages lecteur/écrivain mais coûte du tempdb/de la version store et ne protège pas des verrous de schéma (Sch-M) lors d'un DROP/ALTER, d'un TRUNCATE ou d'un switch de partition.
  • NOLOCK partout : évite les blocages mais autorise des lectures sales (doublons ou lignes manquantes en cours de chargement). Acceptable seulement sur des tables chargées par basculement atomique.
⚠️ Piège 1 — Verrou de schéma pendant la consolidation

· Symptôme : les visuels DirectQuery se figent pendant quelques minutes la nuit. Cause : TRUNCATE/DROP/ALTER ou SWITCH prend un verrou Sch-M, que toutes les requêtes en lecture attendent. Remède : charger en table de préparation puis SWITCH ou renommage atomique court ; fenêtre de maintenance ; ou couper DirectQuery pendant la consolidation (modèle en Import, ou réplica en lecture).

⚠️ Piège 2 — Tempête de requêtes à l'ouverture d'un rapport

· Symptôme : CPU à 100 % à 9 h, retombe vers 10 h. Cause : tous les utilisateurs ouvrent la même page DirectQuery ; aucun cache. Remède : agrégations en Import, réduction des visuels par page, option « réduire le nombre de requêtes » (segments appliqués via bouton), cache de requêtes de la capacité Premium/Fabric.

⚠️ Piège 3 — Limite de lignes retournées

· Symptôme : « le jeu de résultats dépasse la limite de lignes » (de l'ordre de 1 million de lignes sur capacité partagée ; réglable en Premium selon les paramètres). Cause : visuel table/matrice non agrégé. Remède : agréger, filtrer en amont, pagination par visuel de table à détail limité.

🟡 Pratique — DTU/vCore saturés#

Symptômes : requêtes en attente, RESOURCE_SEMAPHORE, LOG_RATE_GOVERNOR, SOS_SCHEDULER_YIELD élevés, erreurs de délai (Timeout expired), CPU > 90 % soutenu, ou gouverneur de journal qui plafonne les écritures de la consolidation.

⚠️ Piège 4 — Plafond d'IO journal masqué

· Symptôme : consolidation lente alors que CPU à 30 %. Cause : le débit d'écriture du journal de transactions est plafonné par le niveau de service (attente LOG_RATE_GOVERNOR). Remède : réduire le volume journalisé (chargements par lots, columnstore, INSERT ... SELECT vers une table neuve), réduire les index à maintenir, ou monter temporairement de niveau.

⚠️ Piège 5 — Un seul gros UPDATE · Symptôme : transaction géante, journal plein, annulations très longues. Cause : mise à jour de dizaines de millions de lignes en une fois. Remède : traiter par lots (50 000 à 500 000 lignes) avec points de reprise ; privilégier INSERT dans une table neuve + SWITCH.

⚠️ Piège 6 — Pool élastique et voisinage

· Symptôme : performances irrégulières sans changement de code. Cause : une autre base du pool consomme le budget. Remède : limites min/max par base, séparer les bases critiques, ou sortir la base du pool.

Élasticité et mesure de performance#

🟡 Pratique — Pourquoi les chronomètres mentent#

Sur Azure SQL, trois éléments font varier un chronométrage : le matériel mutualisé (voisins dans la même ressource physique, pools), le cache (premier passage à froid vs ensuite), et le plan (statistiques ou compatibilité qui changent). Sur des environnements de développement partagés, des écarts de l'ordre de ×2 d'une exécution à l'autre sont plausibles.

Protocole honnête de mesure :

  1. Fixer le niveau de service et le niveau de compatibilité, les noter.
  2. Mesurer le temps CPU et les lectures logiques (SET STATISTICS TIME, IO ON ou Query Store), pas le temps horloge seul.
  3. Alterner les variantes A/B/A/B (jamais A puis B, jamais en parallèle sur la même ressource).
  4. Répéter ≥ 5 fois, retenir la médiane et l'écart.
  5. Mesurer à froid et à chaud séparément.
⚠️ Piège 7 — Conclure d'un seul passage

· Symptôme : « l'optimisation a gagné 40 % » puis disparaît en recette. Cause : variabilité d'environnement, cache chaud. Remède : protocole ci-dessus ; critère de réussite exprimé en CPU et en lectures.

⚠️ Piège 8 — Serverless mis en pause

· Symptôme : la première actualisation du matin échoue ou dure plus longtemps. Cause : reprise de la base (de l'ordre de la minute) ; délai de connexion dépassé. Remède : désactiver la pause pour la production (ou délai de pause long), « réveiller » la base par une requête légère avant l'actualisation, tolérance de nouvelle tentative dans le pipeline.

⚠️ Piège 9 — Montée de niveau en pleine charge

· Symptôme : coupures de connexion de quelques secondes. Cause : un changement de niveau de service bascule les connexions en fin d'opération. Remède : hors heures de pointe ; stratégie de reconnexion avec nouvelle tentative dans les pipelines ; éviter de changer pendant une actualisation.

Réseau, pare-feu et connexion#

🟡 Pratique — Pannes réseau typiques#

⚠️ Piège 10 — Pare-feu serveur

· Symptôme : Desktop OK, service KO (« client avec l'adresse IP … non autorisé »). Cause : l'IP de l'utilisateur est autorisée, pas le service. Remède : autoriser « services Azure » (large) ou plages ciblées, ou endpoint privé + passerelle de réseau virtuel ; vérifier la balise de service PowerBI.

⚠️ Piège 11 — DNS privé

· Symptôme : le nom du serveur se résout en IP publique depuis le réseau d'entreprise, qui est refusée. Cause : zone DNS privée privatelink.database.windows.net non liée au réseau. Remède : lier la zone au VNet, ou redirecteurs conditionnels ; tester avec nslookup depuis la machine de la passerelle.

⚠️ Piège 12 — Passerelle indisponible

· Symptôme : toutes les actualisations d'un domaine échouent en même temps. Cause : passerelle sur VM unique arrêtée, mise à jour, certificat. Remède : cluster de passerelles (≥ 2 nœuds), supervision, mises à jour planifiées ; ou passerelle de réseau virtuel gérée.

⚠️ Piège 13 — Délai de connexion et de commande

· Symptôme : Timeout expired à la connexion ou à l'exécution. Cause : base en pause, saturation de workers, requête trop longue. Remède : augmenter le délai de commande dans la source si légitime, mais surtout corriger la cause ; distinguer délai de connexion (réseau/pause) de délai de commande (requête).

⚠️ Piège 14 — Pas de pare-feu sur la passerelle sortante

· Symptôme : passerelle installée mais « hors ligne ». Cause : ports sortants (HTTPS, Service Bus) bloqués par le pare-feu d'entreprise. Remède : ouvrir les destinations documentées (liste en vigueur à consulter dans la documentation officielle de la passerelle).

Identités et jetons#

🟡 Pratique — Les pannes d'identité#

⚠️ Piège 15 — Identifiants expirés ou changés

· Symptôme : l'actualisation échoue du jour au lendemain (« informations d'identification non valides »). Cause : mot de passe SQL renouvelé, compte de service désactivé, secret d'application Entra expiré. Remède : compte de service sans expiration surprise ou, mieux, principal de service/identité managée avec rotation planifiée et alerte à J-30.

⚠️ Piège 16 — Authentification Entra et jeton absent

· Symptôme : Login failed for user '<token-identified principal>'. Cause : la base n'a pas créé l'utilisateur externe (CREATE USER [x] FROM EXTERNAL PROVIDER), ou l'administrateur Entra n'est pas défini sur le serveur, ou le jeton n'a pas la bonne audience. Remède : définir l'admin Entra ; créer l'utilisateur dans chaque base ; accorder les rôles ; vérifier le locataire.

⚠️ Piège 17 — SSO DirectQuery non activé

· Symptôme : tous les utilisateurs voient les mêmes données, la RLS SQL ne s'applique pas. Cause : la source du modèle utilise l'identité du propriétaire et non « Single Sign-On Entra ID pour les requêtes DirectQuery ». Remède : activer l'option dans les paramètres de la source ; tester avec deux comptes aux droits différents.

⚠️ Piège 18 — Principal de service non autorisé

· Symptôme : les appels d'API (actualisation, déploiement) répondent 401/403. Cause : les principaux de service n'ont pas été autorisés au niveau du locataire (paramètre d'administration) ou n'ont pas de rôle sur l'espace de travail. Remède : groupe de sécurité dédié autorisé dans le portail d'administration, rôle Membre/Contributeur sur l'espace.

⚠️ Piège 19 — MFA et comptes interactifs

· Symptôme : l'actualisation échoue après activation de l'authentification multifacteur. Cause : un compte utilisateur « technique » est devenu soumis à l'accès conditionnel. Remède : plus de comptes utilisateurs pour des automates ; identités de service avec stratégies d'accès conditionnel adaptées.

⚠️ Piège 20 — Le compte de déploiement n'a pas les droits

· Symptôme : un kit d'installation du datamart « réussit » mais n'a pas créé certains objets. Cause : droits insuffisants (non propriétaire de base) ou erreurs masquées par un outil qui renvoie 0. Remède : donner db_owner au compte de déploiement sur les bases cibles, exécuter le kit avec arrêt à la première erreur et vérifier les journaux, pas seulement le code retour.

Limites du service d'actualisation#

🟡 Pratique — Nombre, durée, concurrence#

Repères (état 2026-10, à vérifier sur la page officielle) : 8 actualisations planifiées par jour en capacité partagée (Pro), jusqu'à 48 en Premium/Fabric ; 2 h maximum en partagé, 5 h en dédié ; concurrence limitée par capacité (file d'attente au-delà).

⚠️ Piège 21 — Actualisations en cascade qui se marchent dessus

· Symptôme : actualisations en attente puis échec, mémoire insuffisante. Cause : N modèles planifiés à la même heure sur une capacité. Remède : décaler, limiter la parallélisation, actualiser par partitions ; surveiller l'application de métriques de capacité.

⚠️ Piège 22 — Le modèle ne se met à jour que par fenêtre

· Symptôme : les utilisateurs veulent « du temps réel » alors que 8 actualisations/jour sont le maximum. Cause : exigence mal posée. Remède : clarifier la fraîcheur vraiment utile ; table hybride, ou DirectQuery ciblé, ou Direct Lake via mirroring.

⚠️ Piège 23 — Actualisation incrémentielle qui retraite tout

· Symptôme : durée identique à une actualisation complète. Cause : étape Power Query qui casse le query folding (fonctions non traduisibles, ordre des étapes), ou parametres RangeStart/RangeEnd mal appliqués. Remède : vérifier la requête native ; faire le filtrage de date en première étape ; passer par une vue SQL.

⚠️ Piège 24 — Partitions figées devenues fausses

· Symptôme : chiffres historiques incorrects malgré une correction en base. Cause : la politique incrémentielle n'actualise pas les périodes anciennes. Remède : actualisation ciblée de la partition (XMLA/API améliorée) ou « détection de changements » sur une colonne de dernière modification ; procédure de reprise d'historique documentée.

Taille de modèle et licences#

🟡 Pratique — Limites et licences#

Ordres de grandeur (à vérifier) : ~1 Go par modèle en licence Pro, des dizaines de Go possibles en capacité dédiée avec le format de grand modèle (limite = mémoire de la référence). La mémoire sert aussi pendant l'actualisation : un modèle de 8 Go peut en demander ~16 Go le temps d'une actualisation complète (copie existante + nouvelle).

⚠️ Piège 25 — Modèle trop gros pour l'actualisation

· Symptôme : erreur de mémoire pendant l'actualisation, alors que le modèle « tient » en lecture. Cause : doublement transitoire de la mémoire. Remède : incrémentiel, retrait de colonnes à haute cardinalité (identifiants, horodatages à la seconde), division date/heure, agrégations, ou capacité supérieure.

⚠️ Piège 26 — Licences utilisateur

· Symptôme : des collègues ne voient pas le rapport. Cause : sans capacité dédiée (ou selon la licence Fabric/Premium), le lecteur doit avoir une licence Pro/Premium par utilisateur ; avec une capacité suffisante, les lecteurs peuvent être « gratuits » (selon la référence). Remède : cartographier lecteurs/auteurs et choisir le modèle de licence ; voir coût, licences et capacité.

Compatibilité et fonctions#

🔴 Expert — Niveau de compatibilité et comportements#

Le niveau de compatibilité d'une base Azure SQL (130, 140, 150, 160, 170 selon l'évolution du moteur — vérifier l'état courant) conditionne des fonctions de traitement de requêtes. Exemples : l'inlining des UDF scalaires n'est disponible qu'à partir du niveau 150 ; le traitement par lots sur rowstore et le feedback d'allocation de mémoire arrivent aussi avec les niveaux récents ; l'estimation de cardinalité change à 120/140+.

⚠️ Piège 27 — Fonction scalaire sur ancien niveau

· Symptôme : une vue appelant une UDF scalaire est nettement plus lente en DirectQuery (parfois d'un ordre de grandeur). Cause : niveau de compatibilité 130 : pas d'inlining, exécution ligne à ligne et plan sans parallélisme. Remède : relever le niveau (après test de régression, Query Store comme filet), ou déplier la fonction dans la requête (jointures ou CASE), ou la convertir en fonction table en ligne.

⚠️ Piège 28 — Changement de niveau sans filet

· Symptôme : certaines requêtes régressent après passage à un niveau supérieur. Cause : nouvel estimateur de cardinalité. Remède : activer Query Store en mode lecture/écriture avant ; passer au niveau cible ; comparer ; forcer le plan précédent pour les rares régressions ; réglage automatique FORCE_LAST_GOOD_PLAN.

⚠️ Piège 29 — Fonctions non pliables

· Symptôme : le rapport charge toute la table avant de filtrer. Cause : fonctions M sans équivalent SQL (Text.Proper, certaines conversions) cassent le folding. Remède : transformer en SQL (vue), ou conserver les transformations non pliables après les étapes pliables.

💡 Astuce d'expert

Dans un environnement de déploiement par kits, gardez une version du niveau de compatibilité par environnement dans le code (ALTER DATABASE ... SET COMPATIBILITY_LEVEL) et testez en bas avant le haut.

Collation, accents et multilingue#

🟡 Pratique — La langue casse en silence#

  • La collation détermine tri, comparaison et encodage des colonnes varchar. Une collation non UTF-8 stocke les caractères hors page de code comme ?.
  • Un modèle multilingue (libellés traduits au niveau des métadonnées du modèle : cultures, traductions de tables/colonnes/mesures) s'appuie sur des textes corrects en base (pas de mojibake).
  • Les fichiers de scripts SQL/PowerShell contenant des accents doivent rester en UTF-8 avec BOM pour être lus correctement par SSMS, sqlcmd et PowerShell 5.1 ; UTF-8 sans BOM est mal lu par SSMS/PowerShell 5.1 ; cp1252 est perdu par sqlcmd en UTF-8.
⚠️ Piège 30 — Mojibake dans les libellés

· Symptôme : « Opération » à la place de « Opération ». Cause : un fichier UTF-8 lu comme cp1252 (ou inversement) à l'installation ou à l'import. Remède : normaliser l'encodage des scripts (UTF-8 avec BOM), spécifier l'encodage explicitement dans les outils, tester avec un libellé « sentinelle » accentué dans la recette.

⚠️ Piège 31 — Collation insensible aux accents

· Symptôme : « Café » et « Cafe » regroupés, ou clés en doublon refusées. Cause : collation AI. Remède : collation sensible aux accents pour les libellés métier ; différencier le comportement par colonne (COLLATE) plutôt que par base.

⚠️ Piège 32 — Tri différent entre base et modèle

· Symptôme : l'ordre des libellés diffère entre une requête SQL et le visuel. Cause : le tri du modèle suit sa propre culture/collation, indépendante de celle de la base. Remède : colonne de tri explicite (numéro d'ordre) pour les libellés qui comptent (mois, statuts), plutôt que de compter sur l'ordre alphabétique.

Fuseaux horaires et dates#

🟡 Pratique — Le temps est une dimension piégeuse#

Azure SQL Database fonctionne en UTC ; GETDATE() renvoie l'heure UTC. Les horodatages d'une application terrain sont souvent en heure locale de l'appareil, parfois sans fuseau. Le service Power BI évalue NOW()/TODAY() en UTC (sauf calcul explicite dans M ou DAX).

⚠️ Piège 33 — Décalage horaire des données du jour

· Symptôme : les visites de 23 h apparaissent le lendemain, ou « aujourd'hui » est vide jusqu'à 2 h. Cause : UTC vs heure locale ; TODAY() en UTC. Remède : stocker UTC et heure locale (datetimeoffset ou deux colonnes) ; dimension de dates/heures locale calculée dans le datamart ; AT TIME ZONE 'Romance Standard Time' pour convertir (gère l'heure d'été) ; paramètre de décalage dans le modèle pour les mesures « du jour ».

Autres cas : la date d'exploitation d'une consolidation doit être un paramètre (jamais GETDATE() dans les procédures de consolidation) pour rejouer un jour passé à l'identique (idempotence). Les datetime n'ont pas de précision de 1 ms mais de 3,33 ms ; préférer datetime2.

RLS et rétro-filtrage#

🔴 Expert — Quand une mesure change selon le rôle#

⚠️ Piège 34 — Comptes différents selon le rôle

· Symptôme : « nombre de produits distincts » vaut 120 pour un directeur et 45 pour un commercial, alors que le catalogue est identique. Cause : la RLS filtre une dimension ; le filtre se propage vers les faits puis, via un filtre bidirectionnel ou securityFilteringBehavior, remonte vers une autre dimension. Remède : limiter la propagation (sens unique), calculer la mesure sur la dimension sans passer par les faits, ou documenter que la mesure est conditionnelle au périmètre ; tester chaque rôle.

Pièges associés : (a) une RLS SQL ne s'applique pas à un modèle en Import ; (b) une RLS modèle ne protège pas l'accès au point de terminaison SQL (les deux couches ne se substituent pas) ; (c) un « super-utilisateur » doit être modélisé explicitement (rôle sans filtre), pas par absence de règle ; (d) la clé de sécurité (login) doit être identique entre table de droits et USERPRINCIPALNAME().

Coûts#

🟡 Pratique — Où l'argent s'échappe#

  • Calcul toujours allumé : un environnement de test au niveau de production, 24 h/24.
  • Serverless qui ne dort jamais : une requête de supervision toutes les 5 minutes empêche la pause.
  • Stockage et sauvegardes : la rétention longue (LTR) et le stockage de sauvegarde au-delà du volume inclus sont facturés.
  • Double capacité : Power BI/Fabric + Azure SQL ; l'actualisation fréquente coûte des deux côtés.
  • Réseau : sorties de données inter-régions, passerelles, endpoints privés (coût par endpoint et par volume).
  • Absence de réservations : les engagements de 1 ou 3 ans (réservations vCore, plans d'épargne) réduisent significativement le tarif de calcul stable (le pourcentage dépend de l'offre, à vérifier).
✅ Bonne pratique

Étiqueter (tags) chaque ressource par environnement et projet, budgets et alertes Azure Cost Management, revue mensuelle. Voir pilotage coût et valeur.

🧪 Exemple

Une base de test conservée en General Purpose 8 vCore alors qu'elle sert deux jours par mois : passer en serverless (min 0,5 vCore, pause) ramène le coût de calcul à une fraction (ordre de grandeur : de 90 % de réduction possible, selon les durées d'activité), au prix d'un temps de reprise.

Données, déploiement et gouvernance#

🟡 Pratique — Les autres pièges de projet#

⚠️ Piège 35 — Colonne renommée en base

· Symptôme : « La colonne X de la table Y est introuvable » à l'actualisation. Cause : renommage côté datamart sans adapter le modèle. Remède : vues d'exposition à contrat stable ; pour toute rupture, ajouter la nouvelle colonne, migrer le modèle, retirer l'ancienne ensuite.

⚠️ Piège 36 — Suppression/recréation de mesure

· Symptôme : des rapports clients perdent leurs visuels. Cause : l'identifiant interne (lineageTag) de la mesure a changé. Remède : modifier en place ; si suppression indispensable, publier une note de rupture.

⚠️ Piège 37 — Environnement de test non représentatif

· Symptôme : tout va bien en test, pas en production. Cause : volumétrie, droits, réseau ou niveau de service différents. Remède : environnement de recette à volumétrie proche, données anonymisées ; documenter les différences ; voir recette et validation métier.

⚠️ Piège 38 — Données personnelles dans les environnements

· Symptôme : des données client réelles en développement. Cause : copie de production sans anonymisation. Remède : masquage dynamique, jeux anonymisés, accès restreints ; voir sécurité, confidentialité, conformité.

⚠️ Piège 39 — Pas de stratégie de reprise

· Symptôme : une erreur humaine détruit une table, personne ne sait comment restaurer. Cause : confiance dans « le cloud sauvegarde tout ». Remède : restauration à un instant dans le temps (PITR) testée une fois par trimestre, rétention documentée, procédure écrite ; rappel : la sauvegarde ne remplace pas la discipline de déploiement.

Catalogue récapitulatif des 39 pièges#

Le catalogue ci-dessous synthétise les pièges numérotés 1 à 39 ci-dessus pour une consultation rapide. Ordre : fréquence × gravité estimée (appréciation d'expert, contexte : projet de reporting d'entreprise sur Azure SQL).

# Famille Symptôme Cause racine Remède court Gravité
1 Perf Visuels figés la nuit Verrou de schéma (Sch-M) Table de préparation + SWITCH 4/5
2 Perf CPU 100 % à 9 h Tempête DirectQuery Agrégations, moins de visuels 3/5
3 Perf Limite de lignes Visuel non agrégé Agréger, filtrer 2/5
4 Perf Écritures lentes, CPU bas Plafond du journal Lots, moins de journal 4/5
5 Perf Journal plein UPDATE géant Lots, SWITCH 4/5
6 Perf Irrégularité Voisin de pool Limites, isoler 3/5
7 Mesure Gains qui disparaissent Variabilité Protocole CPU/alternance 3/5
8 Mesure 1ʳᵉ actualisation KO Serverless en pause Désactiver pause / réveil 3/5
9 Mesure Coupures brèves Changement de niveau Hors pointe, reconnexion 2/5
10 Réseau Desktop OK, service KO Pare-feu serveur Plages, endpoint privé 4/5
11 Réseau IP publique refusée DNS privé Lier la zone 3/5
12 Réseau Toutes actualisations KO Passerelle unique Cluster, VNet gateway 4/5
13 Réseau Timeout expired Pause/saturation Distinguer connexion/commande 3/5
14 Réseau Passerelle hors ligne Ports sortants Ouvrir destinations 3/5
15 Identité Échec du jour au lendemain Identifiants expirés Principal de service, alerte 4/5
16 Identité token-identified principal Utilisateur externe absent CREATE USER ... FROM EXTERNAL PROVIDER 3/5
17 Identité RLS SQL ignorée SSO non activé Activer SSO DirectQuery 5/5
18 Identité 401/403 API Principal non autorisé Groupe autorisé + rôle 3/5
19 Identité Échec après MFA Compte technique Identités de service 3/5
20 Identité Kit « réussi » incomplet Droits insuffisants db_owner, lire les journaux 4/5
21 Limites File d'attente d'actualisations Concurrence Décaler, partitionner 3/5
22 Limites « Temps réel » exigé Besoin mal posé Hybride/Direct Lake 3/5
23 Limites Incrémentiel = complet Folding cassé Vue SQL, filtre d'abord 4/5
24 Limites Historique faux Partition figée Actualisation ciblée 4/5
25 Taille Erreur mémoire Doublon transitoire Incrémentiel, réduire colonnes 4/5
26 Licence Lecteurs sans accès Licence/capacité Cartographier 2/5
27 Compat UDF nettement plus lente Niveau 130 Relever / déplier 4/5
28 Compat Régressions de plan Nouvel estimateur Query Store, forçage 3/5
29 Compat Table chargée entière Folding cassé Vue SQL 3/5
30 Langue Mojibake Encodage de fichier UTF-8 BOM, sentinelle 4/5
31 Langue Regroupements indus Collation AI Collation sensible 3/5
32 Langue Tri différent Culture du modèle Colonne de tri 2/5
33 Temps Données décalées UTC vs local AT TIME ZONE, double stockage 4/5
34 RLS Mesure varie selon rôle Rétro-filtrage Sens unique, tests par rôle 5/5
35 Projet Colonne introuvable Renommage Vue à contrat stable 4/5
36 Projet Rapports clients cassés lineageTag Modifier en place 5/5
37 Projet OK en test, KO en prod Environnement non représentatif Recette proche prod 4/5
38 Projet Données réelles en dev Pas d'anonymisation Masquage 5/5
39 Projet Restauration impossible Pas de stratégie PITR testé 5/5
✅ Bonne pratique

Transformer ce catalogue en liste de contrôle de revue avant chaque mise en production : 11-checklist-de-projet-reporting.md.

Notes /5 : risque par famille#

Appréciations d'expert (5 = risque le plus fort). Contexte : équipe de 3 à 8 personnes, Azure SQL + Power BI en Import majoritaire. Voir NOTATION.

Famille Probabilité Impact Détectabilité (5 = difficile à détecter) Commentaire
Performance DirectQuery 3/5 3/5 2/5 Visible vite, corrigeable par modèle
Mesure de performance trompeuse 4/5 2/5 4/5 On « optimise » sans effet réel
Réseau/pare-feu 3/5 4/5 1/5 Panne franche, diagnostic rapide
Identité/jetons 4/5 4/5 2/5 Expiration silencieuse
Limites d'actualisation 3/5 3/5 2/5 Documentées, anticipables
Taille/mémoire 2/5 4/5 3/5 Croissance lente puis rupture
Compatibilité/fonctions 2/5 4/5 4/5 Lenteur sans erreur
Langue/encodage 3/5 3/5 4/5 Corruption silencieuse
Temps/fuseaux 4/5 3/5 4/5 Chiffres plausibles mais faux
RLS/rétro-filtrage 3/5 5/5 5/5 Faux chiffres selon le profil, très discret
Coûts 4/5 3/5 3/5 Dérive progressive
🤖 IA

L'IA excelle à expliquer un message d'erreur et à proposer une liste de causes ; elle est moins fiable pour hiérarchiser la cause réelle dans votre contexte, et peut inventer des limites chiffrées. Garde-fou : toute valeur de limite ou de tarif se vérifie dans la documentation officielle. Voir 08-sqlserver-saas-ia.md.

Voir aussi#

✻ Rédigé par Claude Sonnet 5.5