J'associe une petite table (1 000 lignes) à une grande table (8 M lignes) dans SQL Server 2008. La jointure utilise un index de couverture non clusterisé sur la grande table, et la jointure peut produire trois plans de requête possibles. J'essaie de comprendre quel plan est le meilleur, mais je veux aussi généraliser ces connaissances afin que la prochaine fois je puisse mieux connaître les heuristiques à utiliser lors de l'examen des statistiques d'E / S SQL.
Le plan n ° 1 est une jointure en boucle et émet des statistiques pour la grande table comme ceci:
Scan count 2582, logical reads 35686, physical reads 1041, read-ahead reads 23052
Le plan n ° 2 est une jointure de fusion et émet des statistiques comme celle-ci:
Scan count 1, logical reads 59034, physical reads 49, read-ahead reads 59004
Le plan n ° 3 est une jointure par hachage et émet des statistiques comme celle-ci:
Scan count 3, logical reads 59011, physical reads 5, read-ahead reads 59010
L'indice de couverture est ordonné par (ID, Date)
. La requête renvoie des données pour environ 50% des ID et, pour chaque ID, renvoie un bloc contigu des 3 mois de données les plus récents, qui représente généralement environ 1/4 ou les lignes de chaque ID. La requête renvoie environ 1/8 du total des lignes de l'index. En d'autres termes, la requête est clairsemée, mais de manière cohérente.
Mon hypothèse est que le plan n ° 1 est horrible pour cette charge de travail, car déplacer la tête de disque environ 2500 fois (ou même 1041 fois) est beaucoup plus cher qu'une analyse de disque séquentielle. Je suppose également que # 3 et # 2 ont des modèles d'E / S similaires, séquentiels (et donc plus efficaces).
Mais existe-t-il un cas où le plan n ° 1 est vraiment le meilleur, où "le meilleur" signifie moins d'impact sur le sous-système d'E / S et moins d'impact sur d'autres requêtes exécutées simultanément?
Ou cela dépend-il vraiment de nombreuses variables comme le type de sous-système de disque que j'ai, la fragmentation d'index, etc. Si "cela dépend", y a-t-il des règles générales pour aborder le problème?
la source
Réponses:
Voici l'accord tueur: en janvier, il en coûtait 12 000 $ pour acheter 864 * Go * de RAM . Vous pouvez en avoir beaucoup pour votre argent en augmentant simplement la RAM de votre serveur au point que vous n'atteindrez jamais une lecture physique (après l'échauffement, bien sûr).
À part cela, il est vraiment difficile de donner une opinion en noir ou blanc sur l'un des points de données que vous présentez. Bien sûr, le plan n ° 1 avait la plupart des lectures physiques, mais êtes-vous certain que tous les tests ont été effectués sur un cache réchauffé de la même manière? Se pourrait-il que # 1 ait réchauffé le cache pour # 2, quelle est votre méthodologie de test pour vous assurer que tous les cas sont considérés sur un terrain plat? Néanmoins, si vous déboursez 500 $ et doublez la RAM, cela aurait-il plus d'importance? # 1 a le moins de lectures logiques ...
Mais alors # 2 bénéficie probablement d'un DOP élevé (qu'un balayage peut être parallèle). Le temps d'horloge murale de # 2 est-il meilleur que # 1 après avoir ajouté suffisamment de RAM?
Combien de ces plans fonctionnent en parallèle? Y a-t-il des dizaines de requêtes demandant simultanément une allocation de mémoire importante pour le hachage de # 3 et créant ainsi une contention pour RESOURCE_SEMAPHORE? Le # 2 fait-il un tri et demande-t-il également une allocation de mémoire? Est-ce que # 1 fonctionnera mieux car il ne nécessite aucune subvention (au moins d'après les informations publiées ...)?
C'est vraiment vraiment relatif et la question que vous posez ressemble plus à la recherche d'une solution pour un système complexe d'équations ... il pourrait simplement y avoir plus d'une solution.
Une chose est sûre: les rangées de 8M doivent tenir dans la RAM avec beaucoup d'espace libre. Ces lectures physiques implorent certaines banques de mémoire.
la source
Pour cette requête apparemment très simple, l'optimiseur produira systématiquement le meilleur plan en fonction de son modèle de coût. Le modèle de coût est assez précis. Ma recommandation serait donc de laisser le choix à SQL Server.
Deuxième recommandation: mesurez la durée des requêtes pour les trois variantes avec un cache actif. Alors décidez. (Ne décidez pas en fonction des lectures et des numérisations, etc.). Ce qui compte pour vous, c'est la durée.)
En général, pour choisir le meilleur type de jointure (ou index), il faut comprendre le fonctionnement des algorithmes de jointure. C'est trop d'informations pour poster ici.
la source
Ignorer le nombre de scans, ce n'est pas important. Concentrez-vous sur la façon de réduire les lectures logiques. Basé sur http://www.practicalsqldba.com/2013/07/sql-server-performance-tuning.html .
la source