Question

Je hérité d'un nouveau système et je suis en train de faire quelques améliorations sur les données. Je suis en train d'améliorer cette table et ne peut pas sembler logique de mes résultats.

J'ai la structure de tableau suivant:

CREATE TABLE [dbo].[Calls](
    [CallID] [varchar](8) NOT NULL PRIMARY KEY,
    [RecvdDate] [varchar](10) NOT NULL,
    [yr] [int] NOT NULL,
    [Mnth] [int] NOT NULL,
    [CallStatus] [varchar](50) NOT NULL,
    [Category] [varchar](100) NOT NULL,
    [QCall] [varchar](15) NOT NULL,
    [KOUNT] [int] NOT NULL)

Ce tableau a environ 220K enregistrements en elle. Je dois retourner tous les documents qui ont une date postérieure à la date spécifique. Dans ce cas 12/1/2009. Cette requête retourne sur les 66k dossiers et il faut environ 4 secondes pour courir. Des systèmes précédents, je travaille sur ce qui semble élevé. Surtout compte tenu de la façon dont peu d'enregistrements dans le tableau. Je voudrais donc apporter cette baisse du temps.

Je me demande donc ce serait de bons moyens pour le mettre bas? J'ai essayé d'ajouter une colonne de date à la table et la conversion de la date de chaîne à une colonne de date réelle. Ensuite, j'ai ajouté un index sur cette colonne de date, mais le temps est resté le même. Étant donné qu'il n'y a pas que beaucoup de dossiers que je peux voir comment une analyse de table pourrait être rapide mais je pense qu'un indice pourrait entraîner cette baisse du temps.

J'ai considérais juste comme les colonnes de l'interrogation mois et l'année. Mais je ne l'ai pas encore essayé. Et voudrait le garder hors de la colonne date si possible. Mais sinon je peux le changer.

Toute aide est appréciée.

EDIT: Voici la requête que je suis en train de courir et tester la vitesse de la table. Je l'habitude de mettre les colonnes, mais juste pour la simplicité je *:

SELECT *
FROM _FirstSlaLevel_Tickets_New
WHERE TicketRecvdDateTime >= '12/01/2009'

EDIT 2: Alors je l'ai mentionné que j'avais essayé de créer une table avec une colonne de date qui contenait les données de recvddate mais comme une date plutôt que d'un varchar. C'est ce que la colonne est TicketRecvdDateTime dans la requête ci-dessus. La requête originale Je courais contre ce tableau est le suivant:

SELECT *
FROM Calls
WHERE CAST(RecvdDate AS DATE) >= '12/01/2009'
Était-ce utile?

La solution

peut-être dû ce qui est appelé le point de basculement dans SQL Server. Même si vous avez l'index approprié sur la colonne, SQL Server peut décidé de faire une table d'analyse de toute façon si le nombre prévu de lignes renvoyées dépasse un certain seuil (le « point de basculement »).

Dans votre exemple, cela semble probable puisque votre tourne 1/4 du nombre de lignes dans la base de données. Ce qui suit est un bon article qui explique ceci: http://www.sqlskills.com/BLOGS/KIMBERLY/category/The-Tipping-Point.aspx

Autres conseils

SELECT * donnera généralement une mauvaise performance.

Soit l'index sera ignoré ou vous finirez avec une recherche de clé / signet dans l'index ordonné en clusters. Peu importe:. Les deux peuvent fonctionner mal

Par exemple, si vous aviez cette requête, et l'index sur TicketRecvdDateTime inclus CallStatus, il serait alors très probablement fonctionner comme prévu. Ce serait

SELECT CallStatus
FROM _FirstSlaLevel_Tickets_New
WHERE TicketRecvdDateTime >= '12/01/2009'

Ceci est en plus de la réponse de Randy Minder. Assez peut clé / recherche de signet être pas cher pour une poignée de lignes, mais pas pour une grande partie des données de la table

Votre requête est plus rapide w / o un indice (ou, plus précisement, est la même vitesse w / ou w / o l'indice) car et l'index sur RecvdDate sera toujours être ignoré dans une expression comme CAST(RecvdDate AS DATE) >= '12/01/2009'. Ceci est une expression non-SARG-mesure, car elle nécessite la colonne à transformer creux une fonction. Pour cet indice événement à considérer , vous devez exprimer vos critères de filtre exactement sur la colonne en cours d'indexation, non pas sur une expression basée sur elle. Ce serait la première étape.

Il y a plusieurs étapes:

  • Débarrassez-vous de la colonne VARCHAR (10) pour les dates et le remplacer par la colonne DATE ou DATETIME appropriée. Stockage de la date et / ou le temps sous forme de chaînes est criblé de problèmes. Non seulement pour l'indexation, mais aussi pour l'exactitude.
  • Une table qui est fréquemment balayé sur une gamme basée sur une colonne (comme la plupart de ces tables de journaux d'appels sont) doivent être regroupés par cette colonne.
  • Il est peu probable que vous avez vraiment besoin très colonnes de yr et mnth. Si vous avez vraiment besoin d'eux, alors vous avez probablement besoin de les sous forme de colonnes calculées.

.

CREATE TABLE [dbo].[Calls](
    [CallID] [varchar](8) NOT NULL,
    [RecvdDate] [datetime](10) NOT NULL,
    [CallStatus] [varchar](50) NOT NULL,
    [Category] [varchar](100) NOT NULL,
    [QCall] [varchar](15) NOT NULL,
    [KOUNT] [int] NOT NULL,
    CONSTRAINT [PK_Calls_CallId] PRIMARY KEY NONCLUSTERED ([CallID]));

CREATE CLUSTERED INDEX cdxCalls ON Calls(RecvDate);

SELECT *
FROM Calls
WHERE RecvDate >= '12/01/2009';

Bien sûr, la structure appropriée de la table et des index doit être le résultat d'une analyse approfondie, en tenant compte tous facteurs impliqués, y compris la performance de mise à jour, d'autres requêtes, etc. Je vous recommande de commencer en passant par tous les les sujets traités dans Design Index .

Pouvez-vous modifier votre requête? Si quelques colonnes sont nécessaires, vous pouvez modifier la clause SELECT pour retourner moins de colonnes. Et, alors vous pouvez créer un index couvrant qui comprend toutes les colonnes référencées, y compris TicketRecvdDateTime.

Vous pourriez créer l'index sur TicketRecvdDateTime, mais vous ne pouvez pas éviter le point de basculement qui @Randy Minder discute. Cependant, une analyse sur l'indice plus petit (plus petit que la table de balayage) retourneraient moins de pages.

En supposant RecvdDate est le TicketRecvdDateTime dont vous parlez:

SQL Server compare les dates comprises entre guillemets simples si le type de champ est DATE. Votre requête est probablement les comparer VARCHAR. essayez d'ajouter une ligne avec '99 / 99 / 0001' et voir si elle apparaît au bas.

Dans ce cas, les résultats de la requête sont incorrects. Modification du type à ce jour.

Notez que VARCHAR ne indexe pas bien, ne DATETIME.

Vérifier le plan de requête pour voir si son aide d'indices. Si le DB est faible par rapport à la RAM disponible, il peut simplement la table tout scan et maintenir la mémoire.

EDIT: En voyant votre CAST modifier / DATETIME, permettez-moi de souligner que l'analyse syntaxique une date d'un VARCHAR est une opération très coûteuse. Vous faites cela 220K fois. Cela va tuer la performance.

vous ne sont également plus vérifiait sur un champ indexé. une comparaison avec une expression impliquant un champ d'index ne pas utiliser l'index.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top