5

gpnxuser と key_value の 2 つのテーブルがあります。

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    |                |
+--------------+--------------+------+-----+---------+----------------+

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 は、gpnxuser.id を参照する FK です。また、「パートナー」と呼ばれるテーブルを参照する FK である gpnxuser.partner_id にもインデックスがあります (これは、この質問にはあまり関係ないと思います)。

partner_id = 64 の場合、gpnxuser に 500K 行あり、key_value の約 6M 行と関係があります。

特定のパートナーに属するユーザーの個別の「key_value.upkey」をすべて返すクエリが必要でした。私はこのようなことをしました:

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

実行するのに永遠にかかります。クエリの説明は次のようになります。

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                                  |
    +----+-------------+-----------+------+----------------------------+--------------------+---------+-----------------------------+--------+----------------------------------------------+

私の質問は次のとおりです。高速に実行でき、必要な結果を取得できるクエリはありますか?

4

2 に答える 2

1

あなたがする必要があるのはEXISTSステートメントを利用することです: これは、一致が見つかるまで部分的なテーブルスキャンのみを引き起こします。

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)

注意。元のクエリでは、group byが誤用されています。distinctの方が適切に見えます。

select DISTINCT upkey from gpnxuser join key_value on 
gpnxuser.id=key_value.user_id where partner_id=1
于 2013-04-19T15:11:30.060 に答える