2013-02-07 3 views
2

J'ai cette requête qui dure plus de 3 minutes. Je cherche à optimiser pour fonctionner en quelques secondes:Optimiser la requête de comptage MySQL, informations complètes fournies

SELECT Count(DISTINCT l.licitatii_id) c 
FROM licitatii_ue l 
     INNER JOIN domenii_licitatii dl 
       ON l.licitatii_id = dl.licitatii_id 
        AND dl.tip_licitatie = '2' 
     INNER JOIN domenii d 
       ON dl.domenii_id = d.domenii_id 
        AND d.tip_domeniu = '1' 
        AND d.status = 1 
WHERE l.status = 1 
     AND l.data_limita >= '1357768800' 

EXPLAIN:

*** row 1 *** 
      table: d 
      type: ref 
    possible_keys: PRIMARY,key_status_tip_domeniu,ind_v1 
      key: key_status_tip_domeniu 
     key_len: 9 
      ref: const,const 
      rows: 39 
      Extra: Using where; Using index 
*** row 2 *** 
      table: dl 
      type: ref 
    possible_keys: PRIMARY,licitatii_id,licitatii_id_2 
      key: PRIMARY 
     key_len: 5 
      ref: web1db1.d.domenii_id,const 
      rows: 1882 
      Extra: Using index 
*** row 3 *** 
      table: l 
      type: eq_ref 
    possible_keys: PRIMARY,data_limita 
      key: PRIMARY 
     key_len: 4 
      ref: web1db1.dl.licitatii_id 
      rows: 1 
      Extra: Using where 

Schéma:

licitatii_ue

PRIMARY KEY (`licitatii_id`), 
    UNIQUE KEY `nr_ue` (`nr_ue`), 
    KEY `nume` (`nume`), 
    KEY `tip_licitatie` (`tip_licitatie`), 
    KEY `surse_ue_id` (`surse_ue_id`), 
    KEY `data_publicarii` (`data_publicarii`), 
    KEY `tara_id` (`tara_id`), 
    KEY `creat` (`creat`), 
    KEY `data_limita` (`data_limita`), 
    FULLTEXT KEY `nume_fulltext` (`nume`,`descriere`) 
) ENGINE=MyISAM 

/*Index Information*/ 
--------------------- 

Table   Non_unique Key_name   Seq_in_index Column_name  Collation Cardinality Sub_part Packed Null Index_type Comment 
------------ ---------- --------------- ------------ --------------- --------- ----------- -------- ------ ------ ---------- --------- 
licitatii_ue   0 PRIMARY      1 licitatii_id  A    136456 (NULL) (NULL)   BTREE     
licitatii_ue   0 nr_ue      1 nr_ue   A    (NULL) (NULL) (NULL) YES  BTREE     
licitatii_ue   1 nume      1 nume    A    68228 (NULL) (NULL)   BTREE     
licitatii_ue   1 tip_licitatie    1 tip_licitatie A     13 (NULL) (NULL) YES  BTREE     
licitatii_ue   1 surse_ue_id     1 surse_ue_id  A     1 (NULL) (NULL)   BTREE     
licitatii_ue   1 data_publicarii    1 data_publicarii A    136456 (NULL) (NULL) YES  BTREE     
licitatii_ue   1 tara_id      1 tara_id   A     41 (NULL) (NULL) YES  BTREE     
licitatii_ue   1 creat      1 creat   A    136456 (NULL) (NULL) YES  BTREE     
licitatii_ue   1 data_limita     1 data_limita  A     770 (NULL) (NULL) YES  BTREE     
licitatii_ue   1 nume_fulltext    1 nume    (NULL)    1 (NULL) (NULL)   FULLTEXT    
licitatii_ue   1 nume_fulltext    2 descriere  (NULL)    1 (NULL) (NULL) YES  FULLTEXT 

domenii_licitatii

PRIMARY KEY (`domenii_id`,`tip_licitatie`,`licitatii_id`), 
    KEY `licitatii_id` (`licitatii_id`,`tip_licitatie`), 
    KEY `licitatii_id_2` (`licitatii_id`) 
) ENGINE=InnoDB 

/*Index Information*/ 
--------------------- 

Table    Non_unique Key_name  Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment 
----------------- ---------- -------------- ------------ ------------- --------- ----------- -------- ------ ------ ---------- --------- 
domenii_licitatii   0 PRIMARY     1 domenii_id  A     20 (NULL) (NULL)   BTREE     
domenii_licitatii   0 PRIMARY     2 tip_licitatie A     228 (NULL) (NULL)   BTREE     
domenii_licitatii   0 PRIMARY     3 licitatii_id A    430634 (NULL) (NULL)   BTREE     
domenii_licitatii   1 licitatii_id    1 licitatii_id A    430634 (NULL) (NULL)   BTREE     
domenii_licitatii   1 licitatii_id    2 tip_licitatie A    430634 (NULL) (NULL)   BTREE     
domenii_licitatii   1 licitatii_id_2    1 licitatii_id A    430634 (NULL) (NULL)   BTREE     

Domenii

PRIMARY KEY (`domenii_id`), 
    KEY `key_status_tip_domeniu` (`status`,`tip_domeniu`), 
    KEY `ind_v1` (`domenii_id`,`tip_domeniu`,`status`), 
    KEY `parent_id` (`parent_id`) 
) ENGINE=InnoDB 

/*Index Information*/ 
--------------------- 

Table Non_unique Key_name    Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment 
------- ---------- ---------------------- ------------ ----------- --------- ----------- -------- ------ ------ ---------- --------- 
domenii   0 PRIMARY       1 domenii_id A     79 (NULL) (NULL)   BTREE     
domenii   1 key_status_tip_domeniu    1 status  A     4 (NULL) (NULL) YES  BTREE     
domenii   1 key_status_tip_domeniu    2 tip_domeniu A     11 (NULL) (NULL)   BTREE     
domenii   1 ind_v1        1 domenii_id A     79 (NULL) (NULL)   BTREE     
domenii   1 ind_v1        2 tip_domeniu A     79 (NULL) (NULL)   BTREE     
domenii   1 ind_v1        3 status  A     79 (NULL) (NULL) YES  BTREE     
domenii   1 parent_id       1 parent_id A     79 (NULL) (NULL)   BTREE 

Répondre

1

Vous avez vraiment besoin d'index composés sur vos tables. Vous devriez avoir des clés composées qui aident à optimiser vos jointures ET où les critères. En outre, comme je les ai inclus, le moteur de recherche peut trouver les valeurs pour les jointures directement à partir des index au lieu de retourner aux pages de données réelles. Si vous n'avez qu'une seule colonne dans l'index, la requête ira ensuite aux données brutes à rejoindre. Voyez ce que ça fait pour vous.

Ok, oui, les deux autres index et vous avez ajouté le troisième - n'a pas aidé. Ensuite, j'essaierais d'inverser la requête un peu ... Ne sachant pas exactement les données, mais il semblerait qu'elles soient un certain type d'éléments de catégorie de recherche. Essayez de

select STRAIGHT_JOIN 
     Count(DISTINCT dl.licitatii_id) c 
    from 
     domenii d 
     join domenii_licitatii dl 
      on d.domenii_id = dl.domenii_id 
      AND dl.tip_licitatie = '2' 
      JOIN licitatii_ue L 
       on dl.licitatii_id = L.licitatii_id 
       AND L.status = 1 
       AND L.Data_Limita >= '1357768800' 
    where 
      d.tip_domeniu = '1' 
     and d.status = 1 

ajoutés par les Pentium10

Explain montrent les éléments suivants:

+---+--------+----+--------+---------------------------------------+------------------------+---+----------------------------+------+--------------------------+ 
| 1 | SIMPLE | d | ref | PRIMARY,key_status_tip_domeniu,ind_v1 | key_status_tip_domeniu | 9 | const,const    | 39 | Using where; Using index | 
| 1 | SIMPLE | dl | ref | PRIMARY,licitatii_id,licitatii_id_2 | PRIMARY    | 5 | web1db1.d.domenii_id,const | 1882 | Using index    | 
| 1 | SIMPLE | L | eq_ref | PRIMARY,data_limita,i1    | PRIMARY    | 4 | web1db1.dl.licitatii_id | 1 | Using where    | 
+---+--------+----+--------+---------------------------------------+------------------------+---+----------------------------+------+--------------------------+ 
+0

J'ai ajouté le premier index, l'autre était déjà là. Cela n'aide pas. Ce n'est pas ramassé du tout. – Pentium10

+0

@ Pentium10, voir l'option révisée – DRapp

+0

J'ai ajouté l'explication à votre réponse. Encore seulement l'index primaire est ramassé. Quelle était la logique derrière la réécriture de la requête? – Pentium10

0

Ici, j'ai déplacé la clause WHERE à la fin dans une sous-requête au début, donc il n'a pas de filtrer plus de lignes créées par les INNER JOIN s au la fin, il est déjà filtré correctement à temps pour le premier INNER JOIN. Cela lance 2 requêtes, mais cela devrait être plus rapide.

SELECT Count(DISTINCT l.licitatii_id) c 
FROM (SELECT DISTINCT licitatii_id 
     FROM licitatii_ue l 
     WHERE l.status = 1 
     AND l.data_limita >= '1357768800' 
     ) l 
     INNER JOIN domenii_licitatii dl 
       ON l.licitatii_id = dl.licitatii_id 
        AND dl.tip_licitatie = '2' 
     INNER JOIN domenii d 
       ON dl.domenii_id = d.domenii_id 
        AND d.tip_domeniu = '1' 
        AND d.status = 1 
+0

cela ne suffit pas, il a couru pendant 4 min 56 sec. – Pentium10

+0

Y avait-il un index combiné sur la clause WHERE d'origine? On dirait qu'ils sont là pour les autres colonnes du 'INNER JOIN's. Essayez de créer un index combiné sur 'l.status' et' l.data_limita' dans la table 'licitatii_ue' et relancez ce qui précède. –