2010-05-12 3 views
1

Description deÉliminez analyse complète de la table en raison entre (et GROUP BY)

Selon la commande explain, il y a une plage qui est à l'origine d'une requête pour effectuer une analyse complète de la table (160K lignes). Comment puis-je conserver la condition de plage et réduire le balayage? Je pense que le coupable soit:

Y.YEAR BETWEEN 1900 AND 2009 AND 

code

Voici le code qui a la condition de la plage (la STATION_DISTRICT est probablement superflu).

SELECT                 
    COUNT(1) as MEASUREMENTS,            
    AVG(D.AMOUNT) as AMOUNT,            
    Y.YEAR as YEAR,              
    MAKEDATE(Y.YEAR,1) as AMOUNT_DATE          
FROM                  
    CITY C,                
    STATION S,                
    STATION_DISTRICT SD,             
    YEAR_REF Y FORCE INDEX(YEAR_IDX),          
    MONTH_REF M,               
    DAILY D                
WHERE                 
    -- For a specific city ...            
    --                  
    C.ID = 10663 AND              

    -- Find all the stations within a specific unit radius ... 
    --               
    6371.009 *             
    SQRT(              
    POW(RADIANS(C.LATITUDE_DECIMAL - S.LATITUDE_DECIMAL), 2) + 
    (COS(RADIANS(C.LATITUDE_DECIMAL + S.LATITUDE_DECIMAL)/2) * 
    POW(RADIANS(C.LONGITUDE_DECIMAL - S.LONGITUDE_DECIMAL), 2))) <= 50 AND 

    -- Get the station district identification for the matching station. 
    --                 
    S.STATION_DISTRICT_ID = SD.ID AND         

    -- Gather all known years for that station ... 
    --            
    Y.STATION_DISTRICT_ID = SD.ID AND    

    -- The data before 1900 is shaky; insufficient after 2009. 
    --               
    Y.YEAR BETWEEN 1900 AND 2009 AND       

    -- Filtered by all known months ... 
    --         
    M.YEAR_REF_ID = Y.ID AND   

    -- Whittled down by category ... 
    -- 
    M.CATEGORY_ID = '003' AND 

    -- Into the valid daily climate data. 
    -- 
    M.ID = D.MONTH_REF_ID AND 
    D.DAILY_FLAG_ID <> 'M' 
GROUP BY 
    Y.YEAR 

Mise à jour

Le SQL effectue une analyse complète de la table, qui se traduit par MySQL effectuer une "copie tmp table", comme indiqué ici:

 
+----+-------------+-------+--------+-----------------------------------+--------------+---------+-------------------------------+--------+-------------+ 
| id | select_type | table | type | possible_keys      | key   | key_len | ref       | rows | Extra  | 
+----+-------------+-------+--------+-----------------------------------+--------------+---------+-------------------------------+--------+-------------+ 
| 1 | SIMPLE  | C  | const | PRIMARY       | PRIMARY  | 4  | const       |  1 |    | 
| 1 | SIMPLE  | Y  | range | YEAR_IDX       | YEAR_IDX  | 4  | NULL       | 160422 | Using where | 
| 1 | SIMPLE  | SD | eq_ref | PRIMARY       | PRIMARY  | 4  | climate.Y.STATION_DISTRICT_ID |  1 | Using index | 
| 1 | SIMPLE  | S  | eq_ref | PRIMARY       | PRIMARY  | 4  | climate.SD.ID     |  1 | Using where | 
| 1 | SIMPLE  | M  | ref | PRIMARY,YEAR_REF_IDX,CATEGORY_IDX | YEAR_REF_IDX | 8  | climate.Y.ID     |  54 | Using where | 
| 1 | SIMPLE  | D  | ref | INDEX        | INDEX  | 8  | climate.M.ID     |  11 | Using where | 
+----+-------------+-------+--------+-----------------------------------+--------------+---------+-------------------------------+--------+-------------+ 

Réponse

Après l'utilisation du STRAIGHT_JOIN:

 
+----+-------------+-------+--------+-----------------------------------+---------------+---------+-------------------------------+------+---------------------------------+ 
| id | select_type | table | type | possible_keys      | key   | key_len | ref       | rows | Extra       | 
+----+-------------+-------+--------+-----------------------------------+---------------+---------+-------------------------------+------+---------------------------------+ 
| 1 | SIMPLE  | C  | const | PRIMARY       | PRIMARY  | 4  | const       | 1 | Using temporary; Using filesort | 
| 1 | SIMPLE  | S  | ALL | PRIMARY       | NULL   | NULL | NULL       | 7795 | Using where      | 
| 1 | SIMPLE  | SD | eq_ref | PRIMARY       | PRIMARY  | 4  | climate.S.STATION_DISTRICT_ID | 1 | Using index      | 
| 1 | SIMPLE  | Y  | ref | PRIMARY,STAT_YEAR_IDX    | STAT_YEAR_IDX | 4  | climate.S.STATION_DISTRICT_ID | 1650 | Using where      | 
| 1 | SIMPLE  | M  | ref | PRIMARY,YEAR_REF_IDX,CATEGORY_IDX | YEAR_REF_IDX | 8  | climate.Y.ID     | 54 | Using where      | 
| 1 | SIMPLE  | D  | ref | INDEX        | INDEX   | 8  | climate.M.ID     | 11 | Using where      | 
+----+-------------+-------+--------+-----------------------------------+---------------+---------+-------------------------------+------+---------------------------------+ 

connexes

Merci!

Répondre

2

ONE Demande ... Il semble que vous connaissiez vos données. Ajouter le mot-clé « STRAIGHT » et voir les résultats ...

SELECT STRAIGHT_JOIN ... le reste de votre requête ...

droite-jointure indique MySql pour le faire comme je l'ai INSCRITS. Ainsi, votre table CITY est la première dans la liste FROM, indiquant ainsi que vous attendez que ce soit votre primaire ... En outre, votre clause WHERE de la ville est le filtre immédiat. Cela étant dit, il va probablement voler à travers le reste de la requête ...

Espérons que cela aide ... Il a travaillé pour moi avec des données gouvernementales de millions d'enregistrements interrogés et joint à 10+ tables de recherche où mySql essayait de penser pour moi.

+0

Je suis surpris que MySQL l'a mal optimisé. Ça m'a aidé. Les requêtes prennent maintenant environ la moitié du temps. Encore besoin d'optimiser le serveur MySQL, mais au moins, je n'ai plus besoin de m'inquiéter d'une analyse complète de la table complète. –

0

Afin de faire efficacement entre requêtes que vous allez vouloir un index b arbre sur votre colonne YEAR. par exemple:

CREATE INDEX id_index USING BTREE ON YEAR_REF (YEAR); 

index btree permettent des requêtes de gamme efficaces, si cela est en fait le problème de la racine puis ayant un indice comme celui-ci devrait se débarrasser de l'analyse complète de la table et ont le scanner que la partie de la table c'est dans la gamme.En savoir plus sur btrees sur

Cependant, comme pour tout conseil d'optimisation, vous devez mesurer pour vous assurer que vous ne faites pas plus de mal que de bien. Pouvez-vous modifier la recherche dans un rayon pour effectuer une recherche dans un cadre de délimitation?

+0

Merci, Luke. Toutes les tables ont des index. Certains d'entre eux ont des index sur les index, parce que je suis tellement paranoïaque. ;-) (Je plaisante!) –

0

Vous connaissez la ville de sorte que vous pouvez calculer un cadre de sélection dans votre application.

Peut-être

S.LATITUDE_DECIMAL >= latitude_lower and 
S.LATITUDE_DECIMAL <= latitude_upper and 
S.LONGITUDE_DECIMAL >= longitude_lower and 
S.LONGITUDE_DECIMAL <= longitude_upper 

pourrait être un peu plus rapide?

+0

Pensait à faire juste cela, mais j'aime les cercles. :-) –