Combien de tables est "trop ​​nombreuses" dans un seul SQL SELECT?

En tant que DBA pour MS SQL 2000 et 2005, je vois régulièrement des requêtes select géantes JOINing 7-10 ou même plus de tables. Je trouve, cependant, qu'il existe un certain point passé que les performances ont tendance à souffrir, et la requête devient très difficile à déboguer et / ou à améliorer.

Donc, y a-t-il une «règle empirique» pour savoir quand je devrais considérer d'autres methods de requête, comme les tables temporaires pour get des résultats préliminaires? Ou y a-t-il un point après lequel l'optimiseur de requêtes SQL ne fait pas très bien pour find le meilleur plan?

Un grand nombre de fois vous pouvez atténuer l'odeur visuelle en créant des vues d'aide, je ne pense pas qu'il y ait une règle dure et rapide de combien de joints sont considérés comme mauvais.

Contrairement au encoding procédural, la décomposition de SQL en petits morceaux peut entraîner des requêtes inefficaces.

L'Optimiseur SQL fonctionnera très bien avec des tonnes de jointures de table, et si vous frappez un casse, vous pouvez spécifier l'ordre ou le style de jointure en utilisant des astuces. En réalité, je pense qu'il est très rare d'get des requêtes qui rejoignent plus de 10 tables, mais il est tout à fait possible que cela se produise dans un scénario de type reporting.

Si vous découvrez une situation où vous avez beaucoup de jointures et que vous avez découvert que cette requête est un goulot d'étranglement ET que vous avez tous les index corrects, vous devrez probablement refactoriser. Cependant, gardez à l'esprit que la grande quantité de jointures peut n'être qu'un symptôme et non la cause du problème. La pratique standard pour l'optimization des requêtes doit être suivie (voir profileur, plan de requête, structure de database, logique, etc.)

SQL Server utilise de toute façon tempdb pour les jointures de fusion. Il n'est donc généralement pas nécessaire de créer une table temporaire pour réorganiser une seule requête SELECT.

Cela dépend vraiment de la taille de vos tables, même si vous ne joignez que deux tables si vous avez des loggings de 100M, alors ce sera un process lent de toute façon.

Si vous avez des loggings X dans les tables a et Y dans la table b, si vous les joignez set, vous pouvez récupérer des loggings x * y, dans ce cas, la memory d'échange sera utilisée pendant le process, ça va être lent, comparez cela, les petites requêtes n'utilisent jonly le cache CPU L2 qui a les meilleures performances.

Cependant, si vous avez vraiment besoin de join beaucoup de tables pour atteindre l'objective, je suggère que vos bases de données sont surnormalisées, la 3ème normalisation fonctionne très bien dans la plupart des cas, n'essayez pas de trop cracher l'information, comme il a reconnu être inefficace pour interroger.

Oui, si nécessaire, créez une table pour mettre en cache les résultats de la requête lourde et mettez à jour les champs seulement quand c'est nécessaire, ou même une seule fois par jour.

Je vois aussi des requêtes gigantesques joindre 7-10 tables, mais d'après ce que j'ai vu, l'optimiseur de requêtes semble toujours find le plan le plus efficace – certainement tous les problèmes de performance que je vois dans ces problèmes complexes sont généralement liés à d'autres problèmes (comme les instructions WHERE conditionnelles ou les sous-requêtes nestedes)

L'optimiseur définit une limite de time sur lui-même pour l'empêcher de fonctionner trop longtime. Le problème avec beaucoup de tables est que chacune multiplie le nombre de plans possibles pour l'optimiseur à évaluer (en fait c'est le nombre de jointures, pas de tables en soi). À un moment donné, l'optimiseur est à court de time et utilisera simplement le meilleur plan qu'il a jusqu'à présent, ce qui peut être très mauvais.

Alors, où est ce point? Eh bien, il est très situationnel, et 2005 est beaucoup mieux que 2000, mais ma règle générale est 4-8 pour SQL Server 2000 et 6-16 pour SQL Server 2005.

Il y a d'autres variables impliquées qui ont un impact plus significatif sur le plan global de la requête et la performance, selon mon expérience, telles que:

  • la ligne d'input count pour chaque opérateur de jointure
  • avec quelle efficacité datatables d'input peuvent être récupérées en premier lieu
  • la taille et le type des colonnes jointes (par exemple, les conversions de type, la nullité)

Vous pouvez avoir seulement deux tables jointes set dans une requête, mais si une colonne key est un GUID et l'autre est une représentation varchar d'un GUID, vous n'avez aucun index n'importe où, et les tables sont 2 millions de lignes chacune, alors vous Il y aura probablement de très mauvaises performances.

J'ai déjà codé des requêtes avec 10+ jointures, et l'utilisation judicieuse de quelques index non clusterisés sur des colonnes de foreign keys présente généralement le plus grand avantage sur le plan.