web-dev-qa-db-fra.com

Création d'un index sur un horodatage pour optimiser la requête

J'ai une requête du formulaire suivant:

SELECT * FROM MyTable WHERE Timestamp > [SomeTime] AND Timestamp < [SomeOtherTime]

Je voudrais optimiser cette requête et je pense à mettre un index sur l'horodatage, mais je ne sais pas si cela pourrait aider. Idéalement, je voudrais faire de l'horodatage un index clusterisé, mais MySQL ne prend pas en charge les index clusterisés, à l'exception des clés primaires.

  • MyTable a plus de 4 millions de lignes.
  • Timestamp est en fait de type INT.
  • Une fois qu'une ligne a été insérée, elle n'est jamais modifiée.
  • Le nombre de lignes avec un Timestamp donné est en moyenne d'environ 20, mais peut atteindre 200.
  • Les lignes nouvellement insérées ont un Timestamp supérieur à la plupart des lignes existantes, mais peut être inférieur à certaines des lignes les plus récentes.

Un index sur Timestamp m'aiderait-il à optimiser cette requête?

49
DanielGibbs

Cela ne fait aucun doute. Sans l'index, votre requête doit examiner chaque ligne de la table. Avec l'index, la requête sera à peu près instantanée en ce qui concerne la localisation des bonnes lignes. Le prix que vous paierez est une diminution de performance légère des inserts; mais ce sera vraiment léger.

49
Chris Nash

Vous devez absolument utiliser un index. MySQL n'a aucune idée de l'ordre dans lequel se trouvent ces horodatages, et pour trouver un enregistrement pour un horodatage (ou une plage d'horodatages) donné, il doit parcourir chaque enregistrement. Et avec 4 millions d'entre eux, c'est pas mal de temps! Les index sont votre façon de parler de vos données à MySQL - "Je vais regarder ce champ assez souvent, alors gardez une liste où je peux trouver les enregistrements pour chaque valeur."

Les index en général sont une bonne idée pour les champs régulièrement interrogés. Le seul inconvénient de la définition des index est qu'ils utilisent un espace de stockage supplémentaire, donc à moins que vous ne soyez vraiment à court d'espace, vous devriez essayer de les utiliser. S'ils ne s'appliquent pas, MySQL les ignorera de toute façon.

7
Ryan P

Si vos requêtes utilisent principalement cet horodatage, vous pouvez tester cette conception (agrandissement de la clé primaire avec l'horodatage en première partie):

CREATE TABLE perf (
  , ts INT NOT NULL
  , oldPK 
  , ... other columns 
, PRIMARY KEY(ts, oldPK)
, UNIQUE (oldPK)
) ENGINE=InnoDB ;

Cela garantira que les requêtes comme celle que vous avez publiée utiliseront la clé (primaire) en cluster.

L'inconvénient est que vos insertions seront un peu plus lentes. De plus, si vous avez d'autres indices sur la table, ils utiliseront un peu plus d'espace (car ils incluront la clé primaire plus large de 4 octets).

Le plus grand avantage d'un tel index cluster est que les requêtes avec des analyses de grande portée, par exemple les requêtes qui doivent lire de grandes parties de la table ou la table entière trouveront les lignes associées de manière séquentielle et dans l'ordre souhaité (BY timestamp), qui sera également utile si vous souhaitez regrouper par jour ou semaine ou mois ou année.

L'ancien PK peut toujours être utilisé pour identifier les lignes en gardant une contrainte UNIQUE dessus.


Vous voudrez peut-être aussi jeter un œil à TokuDB , une variante MySQL (et open source) qui autorise plusieurs index clusterisés .

5
ypercubeᵀᴹ

Je ne suis pas en désaccord avec l'importance de l'indexation pour améliorer les temps de requête sélectionnés, mais si vous pouvez indexer sur d'autres clés (et former vos requêtes avec ces index), la nécessité d'indexer sur l'horodatage peut ne pas être nécessaire.

Par exemple, si vous avez une table avec timestamp, category et userId, il peut être préférable de créer un index sur userId à la place. Dans un tableau avec de nombreux utilisateurs différents, cela réduira considérablement l'ensemble restant sur lequel rechercher l'horodatage.

... et si je ne me trompe pas, l'avantage serait d'éviter la surcharge de création de l'index d'horodatage à chaque insertion - dans une table avec des taux d'insertion élevés et des horodatages très uniques, cela pourrait être une considération importante.

Je me bats avec les mêmes problèmes d'indexation basés sur les horodatages et autres clés. J'ai encore des tests à faire donc je peux mettre la preuve derrière ce que je dis ici. J'essaierai de poster en fonction de mes résultats.

Un scénario pour une meilleure explication:

  1. horodatage unique à 99%
  2. userId 80% unique
  3. catégorie 25% unique

    • L'indexation sur l'horodatage réduira rapidement les résultats des requêtes à 1% de la taille de la table
    • L'indexation sur userId réduira rapidement les résultats des requêtes à 20% de la taille de la table
    • L'indexation sur la catégorie réduira rapidement les résultats des requêtes à 75% de la taille de la table
    • L'insertion avec des index sur l'horodatage aura des frais généraux élevés **
    • Malgré notre connaissance que nos insertions respecteront le fait d'avoir des horodatages incrémentiels, je ne vois aucune discussion sur l'optimisation MySQL basée sur des clés incrémentielles.
    • L'insertion avec des index sur userId entraînera une surcharge raisonnablement élevée.
    • L'insertion avec des index sur la catégorie aura des frais généraux raisonnablement bas.

** Je suis désolé, je ne connais pas la surcharge calculée ou l'insertion avec indexation.

4
blackstrype