0
votes

Comment puis-je obtenir le dernier enregistrement pour une pièce d'identité donnée de la manière la plus rapide? (MS SQL)

J'aimerais demander votre aide.

J'ai une table qui ressemble à ceci: xxx

Il y a d'autres colonnes aussi, mais maintenant, ce n'est pas important. Une autre chose, la clé est un keypair (identifiant, séquenceid) et ceux-ci sont indexés dans la table. Ce que je voudrais, c'est d'obtenir la dernière ligne pour les identifiants donnés. Par exemple, si MyID = 1 -> Donne-moi le (1,3), Myid = 2 -> Donne-moi l'enregistrement (2,4) et ainsi de suite. Dans ma table, il y a 500 identifiants et chaque identifiant dispose de 50 000 ID de séquence de sorte que la taille des enregistrements est de 500 * 50 000

ma requête: xxx < P> Malheureusement, ce n'est pas aussi vite que je le veux. Dans mon essai, @myids contient tous les identifiants, 1 à 500 et dans ce cas, l'heure d'exécution est d'environ 1 seconde. Mais je voudrais le rendre plus rapide.

Avez-vous une idée de la façon dont je peux le rendre plus rapide? Peut-être une autre requête qui est meilleure que ce que j'utilise?

Merci pour des réponses.

BR.


7 commentaires

Avez-vous un index sur la table?


Texte de OP: Il existe d'autres colonnes aussi, mais maintenant ce n'est pas important. Une autre chose, la clé est un keypair (identifiant, séquenceid) et ceux-ci sont indexés dans la table.


Vous pourriez essayer d'exister ou de rejoindre au lieu d'entrer. Cependant, avec une requête aussi simple, l'optimiseur choisit probablement le même chemin d'exécution. Vous pouvez également essayer d'utiliser une table temporaire au lieu de la variable de table. Voici quelques articles qui entrent en détail sur les deux sujets: Expliqué .com / 2009/06/16 / in-vs-join-vs-existe et SQLSHACK.COM/WHEN-TURE-TEMPORARY-TABLES-VS-TABLES-VARIES


Comment mesurez-vous le temps?


J'utilise SQL Server Management Studio et vérifie le temps d'exécution à ce sujet.


Veuillez ajouter la définition de votre type de table et Créer des déclarations pour les indices de votre table. Ces détails sont cruciaux en matière d'optimisation des performances.


Pouvez-vous ajouter la définition de @myids? Je voudrais vérifier si vous avez ajouté des index sur celui-ci


6 Réponses :


0
votes

Vous pouvez essayer avec une join interne comme ci-dessous-

SELECT * FROM 
(
    SELECT myId,sequenceId, 
    ROW_NUMBER() OVER(PARTITION BY myId ORDER BY sequenceId DESC) RN
    FROM  myTable
)A
WHERE RN = 1


1 commentaires

Je l'ai essayé avec "Se rejoindre interne" et l'heure d'exécution était plus lente, c'est pourquoi j'utilise "dans"



0
votes

Premier, @myids est une variable de table, n'est-ce pas? Comment déclarez-vous cela? Est-ce indexé? Ajoutez une clé primaire sur celle-ci:

SELECT * 
FROM (
    SELECT TOP (9223372036854775807) myId MyId, MAX(sequenceId) SequenceId
    FROM myTable t
    GROUP BY myId
    ORDER BY myId
) T
WHERE EXISTS (SELECT TOP 1 'X' X from @MyIds m WHERE m.myId = t.myId)


2 commentaires

Le @myids est un type créé dans la procédure de magasin que j'utilise.


J'ai essayé de cette façon mais malheureusement, la performance n'a donc pas été améliorée.



2
votes

Votre requête est correcte et relativement optimale; Vous n'obtiendrez probablement aucune amélioration en la réécrivez d'une autre manière, autre que de remplacer la variable de table avec une table temporaire indexée.

L'optimisation des performances est généralement des indices. Selon que la colonne ID code> est indexée, l'une des options suivantes doit aider: p> xxx pré>

si l'index en cluster sur la table est créé sur le colonne MyID code>, vous pouvez enregistrer un peu d'espace: p>

create table #list (Id int primary key);

insert into #list (Id)
-- Assuming there are no duplicates, otherwise add DISTINCT
select MyId from @MyIds;

SELECT
     t.myId AS 'MyId',
     MAX(t.sequenceId) AS 'SequenceId'
FROM myTable t
  inner join #list l on l.Id = t.myId
GROUP BY t.myId
-- OPTION (RECOMPILE);


5 commentaires

Je ne vois pas comment l'index sans la colonne ID profiterait à la requête de l'OP, car il ne filtre pas par SéquenceID .


Je l'ai essayé avec "Se rejoindre interne" et l'heure d'exécution était plus lente, c'est pourquoi j'utilise "dans"


@Ezlo, "Si l'index en cluster sur la table est créé sur la colonne ID".


@ROGERWOLF, oui même avec le clustered par ID , il utiliserait l'index en cluster et non le non-clusterné uniquement avec le SéquenenceID , mais peut-être que je manque quelque chose .


Bien dit. Plus1 de moi! Notez que vous peut retourner des rangées en ordre décroissant sans perte de parallélisme; Consultez mon message ci-dessous pour éviter de numériser en arrière pour des cas comme celui-ci.



0
votes
select
    id.id as id,
    seq as maxSequence,
    data.someData as someData
from
(select id, max(sequenceId) as seq from #tab group by id) id
left join #tab data on id.id = data.id and id.seq = data.sequenceId

0 commentaires

0
votes

Je recommanderais ce qui suit: xxx

puis pour les performances que vous souhaitez un index sur MyTable (MyID, SéquenceID Desc) .


2 commentaires

L'index ne devrait-il pas être MyTable (MyID, SéquenceID Desc) Pour obtenir le maximum SéquenenceId dans la première correspondance sur MyID ?


@Habo. . . Je pense que c'est un meilleur choix. SQL Server peut être intelligent même avec un indice ascendant.



0
votes

Comme déjà mentionné - si vous avez un index sur MyID, votre requête devrait em> voler. Un index de colonne et / ou Traitement du mode batch peut accélérer de manière spectaculaire les choses. Si vous pouvez ajouter un filtre à votre index, encore mieux. Les tables optimisées de la mémoire et / ou d'autres objets peuvent également accélérer les choses. Tout ce qui dit, permettez-moi d'introduire un nouveau type d'index - l'index virtuel code>. Vous pouvez exploiter Rangeabe ou Jeff Moden's Fntaly .

indexation virtuelle en utilisant dbo.rangeab strong> p>

première échauffement rapide. Créons une requête le retour des nombres 1 à 10 en ordre croissant et décroissant. Faisons-le sans index et avec un plan d'exécution parallèle. P> xxx pré>

retours: strong> p> xxx pré> plan d'exécution: strong> p>

Entrez la description de l'image ici p>

regarder ^^^ Pas de tri !!! Ainsi, pour l'ordre décroissant de votre requête ressemble à ceci: P>

-- Sample data
DECLARE @table TABLE (id INT NOT NULL, sequenceId INT NOT NULL)--, INDEX xxx(id,sequenceId))
INSERT @table VALUES(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(2,4)

SELECT r.RN, sequenceId = MAX(t.sequenceId)
FROM        
(
  SELECT MIN(t.id), MAX(t.id), MIN(t.sequenceId), MAX(t.sequenceId) 
  FROM   @table AS t
) AS mm(Mn,Mx,Mns,Mxs)
CROSS APPLY dbo.rangeAB(mm.Mn,mm.Mx,1,1)   AS r
CROSS APPLY dbo.rangeAB(mm.Mns,mm.Mxs,1,1) AS r2
JOIN        @table                         AS t 
  ON        r.RN = t.id AND r2.RN = Mxs
GROUP BY    r.RN
OPTION (QUERYTRACEON 8649);


0 commentaires