2011-10-31 2 views
2

j'ai une grande base de données de numéros que je suis à la recherche d'un match entre:entre les index manquants de déclaration dans certains cas

Par exemple:

1112203488 

Ma table ressemble à ceci:

| Saton | eATON | info |

J'ai deux de l'indice sur SATON et EATON (nommés s et e)

Donc, mon SQL est la suivante:

SELECT * 
FROM `data2` 
FORCE INDEX (s, e) 
WHERE 1112203488 
BETWEEN `sATON` 
AND `eATON`; 

Donc, en général lorsque l'indice est utilisé, la requête prendra presque zéro le temps (0,02). Cependant, il semble parfois que les statistiques de table dans MySQL prennent la décision de faire une analyse complète de la table à la place, malgré le fait que je forcer l'utilisation des index dans le SQL. C'est un énorme succès en termes de performances car il prend la requête de 0,02 à 120 s.

Voici quelques exemples qui fonctionnent rapidement (en utilisant des index):

67372289 
134744072 

Et les lentes:

1112203488 
1348203839 

Si elle aide les index utilisent BTREE.

+0

Combien de lignes sont les requêtes lentes de retour (et quel est le pourcentage de la table), vs le nombre de lignes (et en pourcentage) les rapides retournons? Les statistiques de la table sont-elles exactes et à jour? –

+0

Les deux index ne peuvent pas être utilisés en même temps. L'un ou l'autre. –

+0

@MikeChristensen Toutes les requêtes retourneront une, Les statistiques sont à jour. – Benjojo

Répondre

1

Si une telle requête renvoie une ligne maximum, cela signifie que les plages (sATON, eATON) ne se chevauchent pas.

Par conséquent, et seulement si les plages ne se chevauchent pas, vous pouvez utiliser cette requête à la place:

SELECT * 
FROM data2 
WHERE sATON = 
     (SELECT MAX(sATON) 
     FROM data2 
     WHERE sATON <= 1112203488 
    ) 
    AND eATON = 
     (SELECT MIN(eATON) 
     FROM data2 
     WHERE eATON >= 1112203488 
    ) 

ou même ce (qui aura besoin d'utiliser un seul indice, le sATON un):

SELECT * 
FROM data2 
WHERE sATON = 
     (SELECT MAX(sATON) 
     FROM data2 
     WHERE sATON <= 1112203488 
    ) 
    AND eATON >= 1112203488 
+0

+1 Bien! De cette façon, vous pouvez utiliser les deux index. –

1

Comme souligné par ypercube, un seul index peut être utilisé pour votre requête en cours. De votre plan d'exécution, je peux voir qu'il utilise l'index s, ce qui signifie qu'il analyse toutes les lignes où la valeur est supérieure à sAton. Pour les valeurs élevées, il s'agira de presque toutes les valeurs, ce qui le rend aussi inefficace qu'un balayage de table complet.

Je voudrais aller avec ypercubes solution suggérée, il devrait être en mesure d'utiliser efficacement les deux index.

L'utilisation de variables se lient sert plusieurs buts:

  1. élimine le risque de SQL injection
  2. Permet la base de données de réutiliser compilées instructions SQL
  3. Réduit le nombre de questions différentes, une meilleure utilisation du cache datbase Pour les questions récemment utilisées

J'ai principalement travaillé avec Oracle, donc je ne suis pas sûr de la validité de 2 et 3 pour mysql.

Si vous voulez savoir comment les utiliser, google pour: mysql bind variable example +your programming language