2013-04-19 3 views
5

ho due tabelle: gpnxuser e key_valueQuery MySQL con ottimizzazione JOIN e GROUP BY. È possibile?

mysql> describe gpnxuser; 
+--------------+--------------+------+-----+---------+----------------+ 
| Field  | Type   | Null | Key | Default | Extra   | 
+--------------+--------------+------+-----+---------+----------------+ 
| id   | bigint(20) | NO | PRI | NULL | auto_increment | 
| version  | bigint(20) | NO |  | NULL |    | 
| email  | varchar(255) | YES |  | NULL |    | 
| uuid   | varchar(255) | NO | MUL | NULL |    | 
| partner_id | bigint(20) | NO | MUL | NULL |    | 
| password  | varchar(255) | YES |  | NULL |    | 
| date_created | datetime  | YES |  | NULL |    | 
| last_updated | datetime  | YES |  | NULL |    | 
+--------------+--------------+------+-----+---------+----------------+ 

e

mysql> describe key_value; 
+----------------+--------------+------+-----+---------+----------------+ 
| Field   | Type   | Null | Key | Default | Extra   | 
+----------------+--------------+------+-----+---------+----------------+ 
| id    | bigint(20) | NO | PRI | NULL | auto_increment | 
| version  | bigint(20) | NO |  | NULL |    | 
| date_created | datetime  | YES |  | NULL |    | 
| last_updated | datetime  | YES |  | NULL |    | 
| upkey   | varchar(255) | NO | MUL | NULL |    | 
| user_id  | bigint(20) | YES | MUL | NULL |    | 
| security_level | int(11)  | NO |  | NULL |    | 
+----------------+--------------+------+-----+---------+----------------+ 

key_value.user_id è FK che i riferimenti gpnxuser.id. Ho anche un indice in gpnxuser.partner_id che è un FK che fa riferimento a una tabella chiamata "partner" (che, penso, non è molto importante per questa domanda).

Per partner_id = 64, ho 500K righe in gpnxuser che hanno una relazione con approssimativamente 6M righe in key_value.

Volevo avere una query che restituiva tutti i distinti "key_value.upkey" per l'appartenenza dell'utente a un determinato partner. Ho fatto qualcosa del genere:

select upkey from gpnxuser join key_value on gpnxuser.id=key_value.user_id where partner_id=64 group by upkey; 

che richiede un'eternità per l'esecuzione. Il spiegano per la query assomiglia:

mysql> explain select upkey from gpnxuser join key_value on gpnxuser.id=key_value.user_id where partner_id=64 group by upkey; 

    +----+-------------+-----------+------+----------------------------+--------------------+---------+-----------------------------+--------+----------------------------------------------+ 
    | id | select_type | table  | type | possible_keys    | key    | key_len | ref       | rows | Extra          | 
    +----+-------------+-----------+------+----------------------------+--------------------+---------+-----------------------------+--------+----------------------------------------------+ 
    | 1 | SIMPLE  | gpnxuser | ref | PRIMARY,FKB2D9FEBE725C505E | FKB2D9FEBE725C505E | 8  | const      | 259640 | Using index; Using temporary; Using filesort | 
    | 1 | SIMPLE  | key_value | ref | FK9E0C0F912D11F5A9   | FK9E0C0F912D11F5A9 | 9  | gpnx_finance_db.gpnxuser.id |  14 | Using where         | 
    +----+-------------+-----------+------+----------------------------+--------------------+---------+-----------------------------+--------+----------------------------------------------+ 

La mia domanda è: esiste una query che può essere eseguito velocemente e ottenere il risultato che voglio?

+0

Sembra che il posto migliore per questa domanda sia: http://dba.stackexchange.com/ –

risposta

1

ciò che devi fare è utilizzano ESISTE dichiarazione: Ciò causerà scansione di tabella parziale fino a quando una corrispondenza trovata e non di più.

select upkey from (select distinct upkey from key_value) upk 
where EXISTS 
    (select 1 from gpnxuser u, key_value kv 
    where u.id=kv.user_id and partner_id=1 and kv.upkey = upk.upkey) 

NB. Nella query originale, il gruppo da viene utilizzato in modo errato: distinto sembra migliore lì.

select DISTINCT upkey from gpnxuser join key_value on 
gpnxuser.id=key_value.user_id where partner_id=1 
+0

Impressionante, funziona perfettamente! –