J'ai déjà fait cela sur des index spécifiques pour faciliter les requêtes lourdes souvent exécutées. En fait, ce qu'ils ont fait est de créer plusieurs index clusterisés: lorsque l'un de ces index est utilisé pour trouver des lignes, aucun travail supplémentaire n'est nécessaire en recherchant le reste des données dans l'index cluster réel (ou le tas s'il n'y a pas d'index cluster réel) .
est-ce une stratégie sensée?
Pour certains index où il était nécessaire de prendre en charge certains modèles de requête, certainement oui.
Mais pour ce faire avec tous les index, je dirais tout aussi certainement non.
Cela va être un gaspillage d'espace à faire là où ce n'est pas réellement nécessaire, et ralentira considérablement les insertions / mises à jour. Cela peut ralentir autant de requêtes de lecture que cela aide, car chaque page d'index contient moins d'enregistrements, de sorte que toute requête devant référencer un morceau de l'index pour le filtrage mais n'utilisant pas toutes les autres colonnes devra accéder à plus de pages. Cela rendra votre base de données plus gourmande en mémoire: ces pages devront être chargées dans le pool de mémoire tampon, éjectant potentiellement d'autres pages utiles si la mémoire est insuffisante. Si la compression est utilisée sur ces index pour essayer d'atténuer l'effet sur les exigences de stockage et de mémoire, elle poussera à la place une charge supplémentaire vers les CPU.
car l'accès se fait via un ORM qui récupère par défaut (mais pas toujours) toutes les colonnes
Il s'agit d'un modèle courant avec une utilisation mal optimisée d'un ORM (ou simplement des ORM naïfs) et dans ces cas, j'ai vu le conseiller d'index de SQL Server (et des outils tiers similaires) suggérer des index avec de nombreuses INCLUDE
colonnes d, donc je serais d'accord avec votre suggestion que c'est pourquoi les index ont été créés de cette façon.
Mais bien que cela puisse rendre toutes ces requêtes un peu plus rapides et certaines beaucoup plus rapides, je soupçonne que dans de nombreux cas, tout avantage est si petit qu'il ne vaut pas l'empreinte mémoire supplémentaire requise par votre ensemble de travail commun, l'espace sur le disque et l'E / S entre le disque et la mémoire.
N'oubliez pas également que l'ORM ne sélectionne peut-être pas toutes les colonnes de toutes les tables touchées par une requête, de sorte que l'avantage ne peut s'appliquer qu'à la cible principale de la demande actuelle, et les index plus grands peuvent pénaliser la requête lorsque d'autres objets sont utilisés pour le filtrage. mais ne renvoyant pas de données ( SELECT * FROM table1 WHERE id IN (SELECT someID FROM table2 WHERE someColumn='DesiredValue')
peut-être).
Une autre considération pour l'espace excédentaire utilisé, en particulier si les données sont volumineuses, est que cela aura un impact sur votre stratégie de sauvegarde: les coûts de stockage et de transfert pour ces sauvegardes, les temps de restauration potentiels, etc.
devrions-nous être préparés à toute différence entre les deux [sur site et AzureSQL]
En général, je pense que les considérations ici seront les mêmes dans chaque cas, bien que tout excès de mémoire / coût d'E / S imposé par les grands index puisse être plus directement visible dans Azure où vous pouvez modifier le niveau de service et donc le coût de l'infrastructure plus facilement plutôt que ayant un ensemble relativement fixe de ressources matérielles. Si vous utilisez des niveaux standard / premium au lieu de la tarification basée sur vcore, vous serez davantage affecté par le coût des E / S en standard, car la prime inclut beaucoup plus d'E / S par DTU. Si vous utilisez des sauvegardes multirégionales ou de la redondance ou d'autres fonctionnalités non locales dans Azure, il peut y avoir un coût de bande passante associé à l'espace supplémentaire pris par des index de largeur excessive.
SELECT
sans spécifier, aORDER BY
commencé à retourner les mêmes lignes qu'avant mais avec un ordre arbitraire différent.