2010-01-21 21 views
29

Je suis principalement un développeur Actionscript et en aucun cas un expert en SQL, mais de temps en temps je dois développer des choses simples côté serveur. Donc, je pensais que je demanderais à des gens plus expérimentés sur la question dans le titre. Je comprends que vous ne gagnez pas beaucoup en définissant un index dans une colonne qui contiendra peu de valeurs distinctes. J'ai une colonne qui contient une valeur booléenne (en fait c'est un petit int, mais je l'utilise comme un drapeau), et cette colonne est utilisée dans les clauses WHERE de la plupart des requêtes que j'ai. Dans un cas théorique «moyen», la moitié des valeurs des enregistrements sera 1 et l'autre moitié, 0. Ainsi, dans ce scénario, le moteur de base de données pourrait éviter une analyse de table complète, mais devra lire beaucoup de lignes de toute façon (nombre total de lignes/2). Donc, devrais-je faire de cette colonne un index? Pour l'anecdote, j'utilise Mysql 5, mais je suis plus intéressé par une logique générale expliquant pourquoi cela n'a pas de sens d'indexer une colonne qui, je le sais, aura une faible cardinalité.Est-il sensé d'utiliser un index qui aura une faible cardinalité?

Merci d'avance.

Répondre

2

Je fais habituellement un simple test d'index "avoir un index" par rapport à "ne pas avoir". Dans mon expérience, vous obtenez la plupart des performances sur les requêtes qui utilisent ORDER BY la colonne indexée. Dans le cas où vous avez un tri sur cette colonne, l'indexation sera très probablement utile.

+0

Merci pour votre réponse. Dans ce cas, je ne suis pas en train de trier sur cette colonne. Il est seulement là pour marquer un enregistrement comme activé/désactivé. Je l'utilise pour la suppression douce, fondamentalement. C'est pourquoi je dois l'utiliser dans la clause WHERE de la plupart des requêtes. –

2

IMHO est d'utilité limitée. Je suppose que dans la plupart des cas, il y a d'autres critères que vous utilisez dans vos requêtes, en plus du drapeau qui aide probablement beaucoup plus.

À 50%, je ferais probablement un benchmarking avec/sans et voir si cela fait une grande différence.

8

Il peut être utile d'inclure le champ booléen dans un index composite. Par exemple, si vous avez une grande table de messages qui doivent généralement être triés par date, mais vous avez également un booléen supprimé champ, donc vous interroger souvent comme ceci:

SELECT ... FROM Messages WHERE Deleted = 0 AND Date BETWEEN @start AND @end 

Vous bénéficierez certainement d'avoir un index composite sur le Supprimé et Date champs.

+0

Merci. Peut-être que je devrais faire quelques recherches sur les indices composites (je connais juste l'existence, mais je ne les ai pas vraiment beaucoup utilisés). J'utilise cette colonne de manière très similaire à votre exemple de code (bien qu'il y ait des jointures et d'autres choses, mais la clause WHERE a toujours cet indicateur pour marquer la suppression douce). –

56

Un index peut aider même sur les champs de faible cardinalité si:

  1. Lorsque l'une des valeurs possibles est très peu fréquente par rapport aux autres valeurs et que vous rechercher.

    Par exemple, il y a très peu de couleur, les femmes aveugles, de sorte que cette requête:

    SELECT * 
    FROM color_blind_people 
    WHERE gender = 'F' 
    

    profiteraient le plus probablement d'un index sur gender.

  2. Lorsque les valeurs ont tendance à être regroupés dans l'ordre de la table:

    SELECT * 
    FROM records_from_2008 
    WHERE year = 2010 
    LIMIT 1 
    

    Bien qu'il existe seulement 3 années distinctes ici, les dossiers avec les années antérieures sont le plus probablement ajouté en premier si grand nombre de dossier doit être scanné avant de renvoyer le premier enregistrement 2010 sinon pour l'index.

  3. Lorsque vous avez besoin ORDER BY/LIMIT:

    SELECT * 
    FROM people 
    ORDER BY 
         gender, id 
    LIMIT 1 
    

    Sans l'indice, un filesort serait nécessaire. Bien qu'il soit quelque peu optimisé pour le LIMIT, il nécessitera une analyse de table complète.

  4. Lorsque l'indice couvre tous les champs utilisés dans la requête:

    CREATE INDEX (low_cardinality_record, value) 
    
    SELECT SUM(value) 
    FROM mytable 
    WHERE low_cardinality_record = 3 
    
  5. Lorsque vous avez besoin DISTINCT:

    SELECT DISTINCT color 
    FROM tshirts 
    

    MySQL utilisera INDEX FOR GROUP-BY, et si vous avez quelques couleurs, cette requête sera instantané même avec des millions d'enregistrements.

    Ceci est un exemple d'un scénario où l'index sur un champ à faible cardinalité est plus plus efficace que celui sur un champ de cardinalité élevé.

Notez que si la performance est DML pas grand-chose sur une question, il est sûr de créer l'index.

Si l'optimiseur pense que l'index est inefficace, l'index ne sera tout simplement pas utilisé.