1

最初のテーブル「tbl1」は次のとおりです。

+---------+---------------------+------+-----+---------+----------------+
| Field   | Type                | Null | Key | Default | Extra          |
+---------+---------------------+------+-----+---------+----------------+
| val     | varchar(45)         | YES  | MUL | NULL    |                |
| id      | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
+---------+---------------------+------+-----+---------+----------------+

そのインデックスで:

+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| tbl1  |          0 | PRIMARY  |            1 | id          | A         |   201826018 |     NULL | NULL   |      | BTREE      |         |
| tbl1  |          1 | val      |            1 | val         | A         |     2147085 |     NULL | NULL   | YES  | BTREE      |         |
| tbl1  |          1 | id_val   |            1 | id          | A         |   201826018 |     NULL | NULL   |      | BTREE      |         |
| tbl1  |          1 | id_val   |            2 | val         | A         |   201826018 |     NULL | NULL   | YES  | BTREE      |         |
| tbl1  |          1 | val_id   |            1 | val         | A         |     2147085 |     NULL | NULL   | YES  | BTREE      |         |
| tbl1  |          1 | val_id   |            2 | id          | A         |   201826018 |     NULL | NULL   |      | BTREE      |         |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+

(追加のインデックス作成の理由はこれです: http://bit.ly/KWx1Xz .)

2 番目のテーブルはほぼ同じです。ただし、インデックスのカーディナリティは次のとおりです。

+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table  | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| tbl2   |          0 | PRIMARY  |            1 | id          | A         |   201826018 |     NULL | NULL   |      | BTREE      |         |
| tbl2   |          1 | val      |            1 | val         | A         |      881336 |     NULL | NULL   | YES  | BTREE      |         |
| tbl2   |          1 | id_val   |            1 | id          | A         |   201826018 |     NULL | NULL   |      | BTREE      |         |
| tbl2   |          1 | id_val   |            2 | val         | A         |   201826018 |     NULL | NULL   | YES  | BTREE      |         |
| tbl2   |          1 | val_id   |            1 | val         | A         |      881336 |     NULL | NULL   | YES  | BTREE      |         |
| tbl2   |          1 | val_id   |            2 | id          | A         |   201826018 |     NULL | NULL   |      | BTREE      |         |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+

タスクは、それらを val 列で内部結合し、id のリストを取得することです (1 秒で実行します)。

「結合」アプローチは次のとおりです。

SELECT tbl1.id FROM tbl1 JOIN tbl2 ON tbl1.val = 'iii' AND tbl2.val = 'iii' AND tbl1.id = tbl2.id;

結果: セット内の 10831 行 ( 55.15 秒)

クエリの説明:

+----+-------------+--------+--------+----------------------------------+---------+---------+---------------------------+------+--------------------------+
| id | select_type | table  | type   | possible_keys                    | key     | key_len | ref                       | rows | Extra                    |
+----+-------------+--------+--------+----------------------------------+---------+---------+---------------------------+------+--------------------------+
|  1 | SIMPLE      | tbl1   | ref    | PRIMARY,val,id_val,val_id        | val_id  | 138     | const                     | 5160 | Using where; Using index |
|  1 | SIMPLE      | tbl2   | eq_ref | PRIMARY,val,id_val,val_id        | PRIMARY | 8       | search_test.tbl1.id       | 1    | Using where              |
+----+-------------+--------+--------+----------------------------------+---------+---------+---------------------------+------+--------------------------+

そして、ここに「in」アプローチがあります:

SELECT id FROM tbl1 WHERE val = 'iii' and id IN (SELECT id FROM tbl2 WHERE val = 'iii');

結果: セット内の 10831 行 ( 1 分 10.15 秒)

説明:

+----+--------------------+--------+-----------------+---------------------------------+---------+---------+-------+------+--------------------------+
| id | select_type        | table  | type            | possible_keys                   | key     | key_len | ref   | rows | Extra                    |
+----+--------------------+--------+-----------------+---------------------------------+---------+---------+-------+------+--------------------------+
|  1 | PRIMARY            | tbl1   | ref             | val,val_id                      | val_id  | 138     | const | 8553 | Using where; Using index |
|  2 | DEPENDENT SUBQUERY | tbl2   | unique_subquery | PRIMARY,val,id_val,val_id       | PRIMARY | 8       | func  |    1 | Using where              |
+----+--------------------+--------+-----------------+---------------------------------+---------+---------+-------+------+--------------------------+

では、ここで質問です。このクエリを微調整して、MySQL が 1 秒でそれを実行できるようにするにはどうすればよいでしょうか?

4

2 に答える 2

2

OK、テーブルごとに 30,000 件以上のレコードでこれをテストしましたが、かなり速く実行されます。

現状では、現在 2 つの大規模なテーブルで結合を実行していますが、最初に各テーブルで「val」の一致をスキャンすると、結合セットのサイズが大幅に削減されます。

私は最初にこの回答をサブクエリのセットとして投稿しましたが、MySQL が外側から実行されるため、ネストされたサブクエリで非常に遅いことに気づきませんでした。ただし、サブクエリをビューとして定義すると、内側から実行されます。

したがって、最初にビューを作成します。

CREATE VIEW tbl1_iii AS (
SELECT * FROM tbl1 WHERE val='iii'
);
CREATE VIEW tbl2_iii AS (
SELECT * FROM tbl2 WHERE val='iii'
);

次に、クエリを実行します。

SELECT tbl1_iii.id from tbl1_iii,tbl2_iii
WHERE tbl1_iii.id = tbl2_iii.id;

雷。

于 2012-06-12T21:17:15.707 に答える
2
SELECT tbl1.id FROM tbl1 JOIN tbl2 ON tbl1.id = tbl2.id and tbl1.val = tbl2.val
where tbl1.val = 'iii';
于 2012-06-12T20:53:27.250 に答える