2016-02-23 3 views
3

J'ai une base de données MySQL avec une table avec environ 160.000 entrées. Lorsque je fais une recherche les requêtes suivantes, il faut environ 0,5 secondes de exeuction:MySQL requête avec deux conditions booléennes prend beaucoup plus de temps que d'interroger chaque condition séparat

SELECT * FROM table WHERE EXTRACT(HOUR FROM date) > 18; 
SELECT * FROM table WHERE EXTRACT(HOUR FROM date) < 3; 

Après avoir combiné les déclarations en une seule requête comme celui-ci

SELECT * FROM table WHERE EXTRACT(HOUR FROM date) > 18 OR EXTRACT(HOUR FROM date) < 3; 

l'exécution prend une éternité. En fait, je n'ai pas vu la requête terminer l'exécution et l'annuler après environ 20 minutes.

Quand je change le OU à et par exemple comme ceci:

SELECT * FROM table WHERE EXTRACT(HOUR FROM date) > 10 AND EXTRACT(HOUR FROM date) < 19; 

Le temps d'exécution est en millisecondes à nouveau.

Peut somenone s'il vous plaît expliquer ce comportement étrange et peut-être suggérer une solution pour interroger les deux conditions avec OR.

Nous vous remercions à l'avance

Répondre

2

Cela fonctionne pour vous

SELECT * FROM table WHERE EXTRACT(HOUR FROM date) not between 3 and 18; 
3

Les performances d'une requête comme la vôtre ne peut pas être optimale: vous utilisez une fonction sur une colonne de date, et même si la date La colonne est indexée, l'index ne peut pas être utilisé.

En tant que solution simple, je voudrais essayer avec une union toute requête:

SELECT * FROM table WHERE EXTRACT(HOUR FROM date) > 18 
UNION ALL 
SELECT * FROM table WHERE EXTRACT(HOUR FROM date) < 3 

tout logiquement équivalente à la forme OU, il pourrait effectuer mieux ... mais aussi peut-être pas!

Une bonne solution consiste à ajouter une nouvelle heure colonne, avec un indice sur elle:

ALTER TABLE table ADD COLUMN date_hour INT; 
ALTER TABLE table ADD INDEX idx_date (date_hour); 

/* do an update once... or use a trigger */ 
UPDATE table SET date_hour = EXTRACT(HOUR FROM date); 

SELECT * FROM table WHERE date_hour > 18 or date_hour < 3;