Comment augmenter les performances des requêtes vierges dans MS SQL Server?

10

J'ai un site Web ASP.NET qui fait sa propre mise en cache indépendante des données et les données ne changent pas pendant de longues périodes, il n'a donc pas besoin d'interroger SQL Server une deuxième fois avec la même requête. J'ai besoin d'améliorer les performances des premières requêtes (vierges) qui vont à ce serveur SQL. Certaines requêtes traitent tellement de données qu'elles peuvent entraîner l'utilisation de SQL Server tempdb. Je n'utilise pas de variables de table temporaire ou de tables temporaires, donc SQL Server décide de l'utiliser tempdbseul quand il en a besoin.

Ma taille de base de données est de 16 Go, j'ai 32 Go de RAM physique disponible sur ma machine serveur.

Je comprends que la stratégie de mise en cache de MS SQL Server essaie de conserver les données dans la RAM pour accélérer les performances de requêtes similaires si elles ont besoin de charger les mêmes données à nouveau. De plus, il essaiera d'utiliser la RAM disponible au lieu de tempdb pour accélérer les performances sans provoquer d'accès au disque.

Je suppose que lorsqu'une requête qui doit stocker quelque chose dans tempdb SQL Server arrive et qu'il n'y a pas assez de RAM disponible, SQL Server a 2 choix:

1) pour décharger certaines données mises en cache et utiliser de la RAM épargnée au lieu de tempdb pour éviter les écritures sur disque

2) conserver les données en cache pour les requêtes futures et commencer à utiliser tempdb, ce qui ralentit les écritures sur le disque.

Je ne sais pas quel choix SQL Server fera dans cette situation, mais je voudrais qu'il fasse le choix n ° 1 car je ne me soucie que des performances des premières requêtes (vierges), car je n'envoie plus jamais la même requête à SQL Server (même si je peux envoyer une requête similaire).

Quelle est la stratégie de mise en cache SQL Server pour ce scénario?

Comment équilibre-t-il l'utilisation de la RAM entre l'évitement de tempdb pour les requêtes vierges et la vitesse des secondes requêtes?

Est-il possible de configurer SQL Server de telle manière qu'il fera le choix n ° 1? Si oui, alors comment?

Sinon, comment puis-je augmenter les performances de toutes les requêtes SQL vierges?

Étant donné que je ne connais pas la stratégie de mise en cache de SQL Server, je souhaite placer la base de données sur le disque RAM. Cela garantira que toute requête vierge a une vitesse de chargement élevée des données non mises en cache même si SQL Server fait toujours le choix n ° 1. Le risque est que SQL Server puisse commencer à utiliser plus de tempdb avec moins de RAM disponible (il ne reste que 16 Go après avoir utilisé 16 Go pour le disque RAM) s'il continue de faire le choix # 2, ce qui ralentira les requêtes vierges qui provoquent des déversements tempdb.

Je suis intéressé par la solution pour SQL 2008 R2, mais je suppose que c'est probablement la même chose pour SQL 2008, SQL 2005 et peut-être SQL 2000.

Clarifications:

Il n'y a aucune autre application en cours d'exécution sur cette boîte, elle est dédiée à SQL Server . Le site Web fonctionne sur une boîte séparée.

Il s'agit de SQL Server 2008 R2 Standard Edition 64 bits sur Windows Server 2008 R2 Enterprise 64 bits.

J'exécute uniquement les requêtes en lecture seule et la base de données est définie en lecture seule .

Supposons qu'il existe déjà de bons index . Cette question concerne SQL Server faisant le choix n ° 1 par rapport au choix n ° 2, comment le fait-il, s'il existe un moyen de le contrôler et si le disque RAM l'aide à faire le bon choix pour les requêtes vierges.

alpav
la source
Qu'est-ce qui vous fait penser que tempdb est utilisé même si vous ne créez pas de tables temporaires? Utilisez-vous des tables distinctes ou groupées?
Détroit de Darin
3
32/64 bits? Physique ou virtuel? Ce serveur est-il dédié à SQL Server ou exécutez-vous également IIS ou d'autres applications sur la même boîte? Avez-vous effectué une analyse du plan d'exécution des requêtes? Pouvez-vous publier des exemples de requêtes et / ou de plans d'exécution? Et un de plus pour la chance ... suivez le guide de Kendra sur la journalisation de sp_whoisactive pendant que votre requête problème est en cours d'exécution et publiez la sortie.
Mark Storey-Smith,
@darinstrait L'explication la plus probable serait un déversement de type ou de hachage.
Mark Storey-Smith,

Réponses:

7

Votre question peut être reformulée comme suit: «Comment fonctionne la subvention de mémoire de requête?». Une bonne lecture sur le sujet est Comprendre l'attribution de mémoire au serveur SQL . Avant qu'une requête soit lancée en exécution, elle peut nécessiter une allocation de mémoire pour les tris et les hachages et d'autres opérations gourmandes en mémoire. Cette allocation mémoire est une estimation . En fonction de l'état actuel du système (nombre de demandes en cours et en attente, mémoire disponible, etc.), le système accorde à la requête une allocation de mémoire jusqu'à la quantité requise. Une fois la mémoire accordée, la requête démarre son exécution (il peut être nécessaire d'attendre dans la file d'attente redoutée du «sémaphore de ressource» avant d'obtenir l'octroi). À l'exécution, l'allocation de mémoire est garantiepar le système. Cette quantité de mémoire peut être partagée avec des pages de données (car elles peuvent toujours vider le disque) mais jamais avec une autre utilisation de la mémoire (c'est-à-dire qu'elle ne peut pas être soumise à «voler»). Ainsi, lorsque la requête commence à demander de la mémoire validée à son octroi, le moteur déploiera ce que vous appelez la `` stratégie # 1 '': les pages de données peuvent être supprimées (vidées si elles sont sales) afin de donner à la requête la mémoire qui lui a été promise. Maintenant, si l'estimation était correcte et que la subvention représentait 100% de la mémoire demandée, la requête ne devrait pas «déborder». Mais si l'estimation était incorrecte (se résume à des estimations de cardinalité, elle est donc soumise à des statistiques obsolètes) ou si la requête n'a pas obtenu l'intégralité de la subvention qu'elle avait demandée, la requête «débordera». C'est à ce moment que tempdb entre en scène et que les performances sont généralement des tanks.

Le seul bouton dont vous disposez pour contrôler quelque chose dans ce processus est le gouverneur de ressources . Étant donné que le RG peut être utilisé pour spécifier un paramètre MIN pour un pool, il peut être utilisé pour réserver de la mémoire pour une certaine charge de travail afin qu'il obtienne réellement l'allocation de mémoire qu'il demande. Bien sûr, après avoir fait l'enquête appropriée qui montre que les allocations de mémoire réduites sont le coupable, et bien sûr après que l'impact sur les autres charges de travail a été évalué. Et testé, bien sûr.

Revenons maintenant à votre question d'origine. Si votre enquête est correcte (un très gros si), je voudrais signaler deux problèmes:

  • vous exécutez dans des requêtes de production qui nécessitent des allocations de mémoire pour un site Web . C'est un gros non. Les allocations de mémoire indiquent des requêtes analytiques qui n'ont pas leur place dans le traitement des requêtes HTTP.
  • vos requêtes ne sont probablement pas des événements qui obtiennent l'allocation de mémoire qu'ils demandent. Encore une fois, plus de non-non pour une charge de travail critique de latence que les sites Web.

Donc, cela me dit que vous avez un problème fondamental de conception et d'architecture. Les sites Web sont guidés par la latence et doivent créer une charge de travail de type OLTP, sans octroi de mémoire et sans pression de mémoire sur les requêtes. Sans parler des déversements. Les requêtes analytiques doivent être exécutées dans des travaux hors ligne et stocker les résultats prétraités pour une disponibilité rapide lorsque les requêtes HTTP le souhaitent.

Remus Rusanu
la source
@Mark: la plupart des requêtes ne nécessitent aucune allocation de mémoire. Seuls quelques opérateurs (notamment tri et jointure de hachage) ont besoin d'un tampon de travail et demandent donc une autorisation. Il s'agit de la «nomenclature» standard. Vous pensez peut - être de l' environnement d'exécution et requête plan d'exécution, dont chaque requête nécessite un et il comprend une mémoire. Une allocation de mémoire est beaucoup plus importante (Mo). Deuxièmement, regardez sys.dm_exec_query_memory_grants: vous avez requested(le max), required(le min) et granted(le réel).
Remus Rusanu
Mes excuses. J'avais ramassé quelque part que le minimum par requête était alloué par le même commis de mémoire, ce qui était incorrect.
Mark Storey-Smith,
Je ne suis toujours pas sûr d'être d'accord avec vos deux points. Toutes sortes de sortes triviales et d'opérations de jointure de hachage nécessitent des subventions au niveau minimum, donc suggérer qu'elles doivent être entièrement éliminées semble excessif. Que les déversements à tempdb de subventions insuffisantes sont un drapeau rouge est certainement raisonnable, mais une interdiction générale de toute opération nécessitant une subvention pourrait placer de nombreuses personnes sur un chemin d'optimisation préventive inutile?
Mark Storey-Smith
OP prétend avoir tous les index nécessaires. Si cela est vrai et que la charge de travail a suffisamment de problèmes d'allocation de mémoire (et même de déversement) pour être perceptible, je dirais que la charge de travail est trop analytique pour un site Web . En fin de compte, l'optimisation des performances est toujours un jeu d' investigation pour déterminer la cause première. Toutes les déclarations générales et les interdictions vont toujours trouver un contre-exemple qui prouve qu'elles sont fausses, c'est une donnée. Le PO a-t-il un problème de conception qui crée une charge de travail trop analytique? Je ne sais pas. Dois-je pense que c'est le cas? Je dirais que 87,5% de confiance est oui.
Remus Rusanu
@Remus: Votre supposition était bonne, mes requêtes de site Web sont 100% analytiques. Il permet aux utilisateurs de construire toutes les requêtes possibles dans l'interface utilisateur pour envoyer toute combinaison possible de filtres, d'agrégats et de regroupements à SQL Server (ce qui, bien sûr, rend l'indexation difficile). Oui, je pourrais les faire fonctionner en mode asynchrone en enregistrant les résultats pour une récupération ultérieure, mais l'objectif est de faire en sorte que toute requête s'exécute si rapidement que le résultat soit immédiatement disponible après 2 à 10 secondes et que la requête analytique est la seule fonction de ce site Web. , Je pense que les rendre asynchrones n'a de sens que s'il existe d'autres requêtes qui ne sont pas analytiques.
alpav
3

Ce que vous n'avez pas mentionné, c'est quel type de requêtes sont exécutées sur la base de données et s'il existe de bons index pour accélérer les performances de vos requêtes.

Vous devez également vous assurer qu'il existe d'autres applications en cours d'exécution sur la même boîte. Même si la boîte a 32 Go de RAM, avez-vous défini un paramètre de mémoire maximale sur le serveur de base de données pour mettre une limite artificielle. S'il existe des applications exécutées sur le même serveur, SQL et les autres applications peuvent être en concurrence pour les ressources et notez que SQL est très gourmand en mémoire.

SQL Server utilisera tempdb pour le tri interne ou les jointures / agrégats de hachage ou les opérateurs de spoule, etc. et vous ne pouvez pas contrôler ce comportement. Ce que vous pouvez faire, c'est limiter la quantité de données renvoyées.

Avez-vous vérifié les statistiques d'attente sur cette case? Chaque fois que SQL Server attend une ressource, SQL Server suit la ressource d'attente et la consultation de ces informations est utile.

Regardez les requêtes de diagnostic de Glenn Berry et ce sera un bon début pour vous.

Regardez également PARAMETERIZATION FORCED comme mentionné dans http://weblogs.sqlteam.com/dang/archive/2009/06/27/Forced-Parameterization-A-Turbo-Button.aspx

Sankar Reddy
la source
ok, supposons qu'il existe déjà de bons index. J'ai oublié de mentionner qu'il s'agit d'une base de données en lecture seule avec des requêtes en lecture seule et qu'aucune autre application ne s'exécute sur la boîte SQl Server.
alpav
Vos statistiques sont-elles à jour? Les bases de données en lecture seule ne peuvent pas créer de statistiques si elles sont manquantes ou obsolètes. Vos données sont-elles biaisées ou ont-elles des valeurs uniques pour la clé? De nombreux facteurs peuvent provoquer ce comportement.
Sankar Reddy
Qu'entendez-vous par «ce comportement»? Je n'ai pas mentionné que quelque chose allait mal. Je veux juste augmenter les performances dans mes circonstances particulières. SQL Server est optimisé pour fonctionner dans n'importe quelle situation, mais il peut ou non ne pas fonctionner de la meilleure façon dans ma situation. Je ne sais pas si je peux faire confiance à SQL Server pour faire un choix équilibré # 1 vs # 2. Chaque fois que je mets de nouvelles données dessus, j'exécute sp_updatestats.
alpav
2
Lorsque vous exécutez sp_updatestats, quel est le taux d'échantillonnage que vous avez choisi. Le ratio par défaut est très échantillon et dépend de la taille de l'index. Si vos requêtes interrogent principalement (uniquement) les nouvelles données et même si vous effectuez sp_updatestats, SQL Server ne peut pas prendre de décisions concernant les plans d'exécution.
Sankar Reddy
2

Cette question se lit actuellement comme une solution à la recherche d'un problème. Vous avez décidé qu'un disque RAM est la solution et vous voulez que quelqu'un valide ce choix. Désolé, ça n'arrivera pas.

Si vous avez mesuré et observé un déversement sur tempdb, cela sera presque certainement dû à une opération de tri ou de hachage et à une allocation de mémoire de requête insuffisante. Selon le volume de données à traiter, cela peut être inévitable, mais de bonnes chances que la requête et / ou l'indexation puissent être améliorées pour l'éviter.

Jetez un œil à Buffer Management pour mieux comprendre comment SQL Server gère la mémoire et SQL Server Memory Management Expliqué pour certains outils de base et requêtes DMV pour comprendre où votre mémoire est allouée.

Sinon, comment puis-je augmenter les performances de toutes les requêtes SQL vierges?

C'est un gros sujet. Publiez la requête et le plan et vous obtiendrez des commentaires ciblés.

Mark Storey-Smith
la source