MySQL非常慢的连接查询

时间:2016-08-14 06:34:57

标签: mysql

我在MySQL中有两个表(MariaDB 6.1.7601)

Table: PT

+---------------+---------------+------+-----+---------+-------+
| Field         | Type          | Null | Key | Default | Extra |
+---------------+---------------+------+-----+---------+-------+
| p_id          | char(32)      | NO   | PRI | NULL    |
| ps_id         | int(3)        | NO   |     | NULL    |
..other 27 fields

此表的索引为(p_id,ps_id)

记录数:1900万

Table: PF

+---------------+---------------+------+-----+---------+-------+
| Field         | Type          | Null | Key | Default | Extra |
+---------------+---------------+------+-----+---------+-------+
| p_id          | char(32)      | NO   | PRI | NULL    |       |
..other 22 fields

记录数:1900万

我想,

1) Select all records exist in PT but not in PF
2) Select all records exist in PF but not in PT
3) Select all records exist in both

我使用左右连接做1)和2)和内连接3)。以下是我正在使用的查询。

Query 1) 

select pt.p_id 
from pt left join pf on pt.p_id = pf.p_id and pt.ps_id=1 
where pf.p_id is null

解释输出:

| id   | select_type | table | type   | possible_keys | key        | key_len | ref          | rows     | Extra  |
|    1 | SIMPLE      | pt    | index  | NULL          | p_id       | 100     | NULL         | 19313237 | Using index |
|    1 | SIMPLE      | pf    | eq_ref | PRIMARY       | PRIMARY    | 96      | pt.p_id      | 1        | Using where; Using index; Not exists |

此查询大约需要 300

Query 2)

select pf.p_id 
from pt right join pf on pt.p_id = pf.p_id and pt.ps_id=1 
where pt.p_id is null

解释输出:

| id   | select_type | table | type   | possible_keys      | key     | key_len | ref         | rows     | Extra                   |
|    1 | SIMPLE      | pf     | index  | NULL              | PRIMARY | 96      | NULL        | 19313269 | Using index             |
|    1 | SIMPLE      | pt     | eq_ref | PRIMARY,p_id      | PRIMARY | 96      | pf.p_id     |        1 | Using where; Not exists |

此查询大约需要 700-1000

Query 3)

select * from pt, pf 
where pt.p_id=pf.p_id 
and pt.ps_id=1

此查询以毫秒为单位给出结果。

其他细节

存储引擎:MyISAM,RAM:8G,CPU:I3,运行查询时的CPU使用率:25%,总RAM使用率:4G,MYISAM密钥缓冲区:2G,应用程序:我的应用程序不需要事务处理。来自外部系统的大量读取。

赞赏任何帮助调优查询1和查询2。

更新1:

不幸的是,我的表崩溃了,所以不得不重新创建表并填充数据。 这是当前的表结构,记录计数和配置文件查询。创建了仅包含相关列的新表pt1和pf1。

表格定义

MariaDB [fp1]> describe pt1;
+-------+----------+------+-----+---------+-------+
| Field | Type     | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| p_id  | char(32) | NO   | PRI | NULL    |       |
| ps_id | int(11)  | NO   |     | NULL    |       |
+-------+----------+------+-----+---------+-------+
2 rows in set (0.00 sec)

MariaDB [fp1]> describe pf1;
+-------+----------+------+-----+---------+-------+
| Field | Type     | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| p_id  | char(32) | NO   | PRI | NULL    |       |
+-------+----------+------+-----+---------+-------+
1 row in set (0.00 sec)

索引

MariaDB [fp1]> show index from pt1;
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
| pt1   |          0 | PRIMARY  |            1 | p_id        | A         |    14170752 |     NULL | NULL   |      | BTREE      |         |               |
| pt1   |          1 | p_id     |            1 | p_id        | A         |    14170752 |     NULL | NULL   |      | BTREE      |         |               |
| pt1   |          1 | p_id     |            2 | ps_id       | A         |    14170752 |     NULL | NULL   |      | BTREE      |         |               |
3 rows in set (0.00 sec)

MariaDB [fp1]> show index from pf1;
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
| pf1   |          0 | PRIMARY  |            1 | p_id        | A         |    13073810 |     NULL | NULL   |      | BTREE      |         |               |
1 row in set (0.00 sec)

记录

MariaDB [fp1]> select count(*) from pt1;
+----------+
| count(*) |
+----------+
| 14170752 |
+----------+

MariaDB [fp1]> select count(*) from pf1;
+----------+
| count(*) |
+----------+
| 13073810 |
+----------+

查询1

查询

select pf1.p_id from pf1 left join pt1 on pf1.p_id = pt1.p_id where pt1.p_id is null;

记录计数

MariaDB [fp1]> select count(pf1.p_id) from pf1 left join pt1 on pf1.p_id = pt1.p_id where pt1.p_id is null;
+-----------------+
| count(pf1.p_id) |
+-----------------+
|         6703180 |
+-----------------+
1 row in set (1 min 52.58 sec)

解释

MariaDB [fp1]> explain select pf1.p_id from pf1 left join pt1 on pf1.p_id = pt1.p_id where pt1.p_id is null;
| id   | select_type | table | type   | possible_keys | key     | key_len | ref             | rows     | Extra
|    1 | SIMPLE      | pf1   | index  | NULL          | PRIMARY | 96      | NULL            | 13073810 | Using index                          
|    1 | SIMPLE      | pt1   | eq_ref | PRIMARY,p_id  | PRIMARY | 96      | fp1.pf1.p_id    |        1 | Using where; Using index; Not exists
2 rows in set (0.00 sec)

显示个人资料

MariaDB [fp1]> show profile;
+------------------------------+------------+
| Status                       | Duration   |
+------------------------------+------------+
| Sending data                 |   0.006756 |
| Waiting for query cache lock |   0.000005 |
| Sending data                 | 118.233962 |
| end                          |   0.000015 |
| query end                    |   0.000005 |
| closing tables               |   0.000003 |
| Unlocking tables             |   0.000011 |
| freeing items                |   0.000007 |
| updating status              |   0.000045 |
| cleaning up                  |   0.000004 |
+------------------------------+------------+
100 rows in set (0.00 sec)

展示资料扩展

MariaDB [fp1]> show profile cpu, block io, swaps for query 1;
| Status                       | Duration   | CPU_user   | CPU_system | Block_ops_in | Block_ops_out | Swaps |
+------------------------------+------------+------------+------------+---------
| Sending data                 |   0.006713 |   0.015600 |   0.000000 |68 |             0 |  NULL |
| Waiting for query cache lock |   0.000006 |   0.000000 |   0.000000 |0 |             0 |  NULL |
| Sending data                 |   0.006843 |   0.000000 |   0.000000 |69 |             0 |  NULL |
| Waiting for query cache lock |   0.000005 |   0.000000 |   0.000000 |0 |             0 |  NULL |
| Sending data                 |   0.006756 |   0.015600 |   0.000000 |66 |             0 |  NULL |
| Waiting for query cache lock |   0.000005 |   0.000000 |   0.000000 |0 |             0 |  NULL |
| Sending data                 | 118.233962 | 113.272326 |   3.478822 |994039 |             0 |  NULL |
| end                          |   0.000015 |   0.000000 |   0.000000 |0 |             0 |  NULL |
| query end                    |   0.000005 |   0.000000 |   0.000000 |0 |             0 |  NULL |
| closing tables               |   0.000003 |   0.000000 |   0.000000 |0 |             0 |  NULL |
| Unlocking tables             |   0.000011 |   0.000000 |   0.000000 |0 |             0 |  NULL |
| freeing items                |   0.000007 |   0.000000 |   0.000000 |0 |             0 |  NULL |
| updating status              |   0.000045 |   0.000000 |   0.000000 |0 |             0 |  NULL |
| cleaning up                  |   0.000004 |   0.000000 |   0.000000 |0 |             0 |  NULL |
100 rows in set (0.00 sec)

查询2

查询

select pt1.p_id from pt1 left join pf1 on pt1.p_id=pf1.p_id and pt1.ps_id=1 where pf1.p_id is null;

记录计数

MariaDB [fp1]> select count(pt1.p_id) from pt1 left join pf1 on pt1.p_id=pf1.p_id and pt1.ps_id=1 where pf1.p_id is null;
+-----------------+
| count(pt1.p_id) |
+-----------------+
|         7800122 |
+-----------------+
1 row in set (59.14 sec)

解释

MariaDB [fp1]> explain select pt1.p_id from pt1 left join pf1 on pt1.p_id=pf1.p_id and pt1.ps_id=1 where pf1.p_id is null;

| id   | select_type | table | type   | possible_keys | key     | key_len | ref             | rows     | Extra
|    1 | SIMPLE      | pt1   | index  | NULL          | p_id    | 100     | NULL            | 14170752 | Using index
|    1 | SIMPLE      | pf1   | eq_ref | PRIMARY       | PRIMARY | 96      | fp1.pt1.p_id    |        1 | Using where; Using index; Not exists
2 rows in set (0.00 sec)

显示个人资料

MariaDB [fp1]> show profile;
+------------------------------+-----------+
| Status                       | Duration  |
+------------------------------+-----------+
| Waiting for query cache lock |  0.000006 |
| Sending data                 |  0.002893 |
| Waiting for query cache lock |  0.000004 |
| Sending data                 | 62.308426 |
| end                          |  0.000014 |
| query end                    |  0.000004 |
| closing tables               |  0.000003 |
| Unlocking tables             |  0.000009 |
| freeing items                |  0.000007 |
| updating status              |  0.000023 |
| cleaning up                  |  0.000006 |
+------------------------------+-----------+

展示个人资料

MariaDB [fp1]> show profile cpu, block io, swaps for query 1;
| Status                       | Duration  | CPU_user  | CPU_system | Block_ops_in | Block_ops_out | Swaps |
| Sending data                 |  0.003193 |  0.000000 |   0.000000 |68 |0|NULL|
| Waiting for query cache lock |  0.000004 |  0.000000 |   0.000000 |0 |0 |  NULL |
| Sending data                 | 62.308426 | 57.423968 |   3.993626 |1056787 |0 |  NULL |
| end                          |  0.000014 |  0.000000 |   0.000000 |0 |0 |  NULL |
| query end                    |  0.000004 |  0.000000 |   0.000000 |0 |0 |  NULL |
| closing tables               |  0.000003 |  0.000000 |   0.000000 |0 |0 |  NULL |
| Unlocking tables             |  0.000009 |  0.000000 |   0.000000 |0 |0 |  NULL |
| freeing items                |  0.000007 |  0.000000 |   0.000000 |0 |0 |  NULL |
| updating status              |  0.000023 |  0.000000 |   0.000000 |0 |0 |  NULL |
| cleaning up                  |  0.000006 |  0.000000 |   0.000000 |0 |0 |  NULL |
+------------------------------+-----------+-----------+------------+-----------

查询3

查询

select pt.p_id from pt1, pf1 where pt1.p_id=pf1.p_id and pt1.ps_id=1

记录计数

MariaDB [fp1]> select count(pt1.p_id) from pt1, pf1 where pt1.p_id=pf1.p_id and pt1.ps_id=1;
+-----------------+
| count(pt1.p_id) |
+-----------------+
|         6370630 |
+-----------------+
1 row in set (55.69 sec)

解释

MariaDB [fp1]> explain select pt1.p_id from pt1, pf1 where pt1.p_id=pf1.p_id and pt1.ps_id=1;
| id   | select_type | table | type   | possible_keys | key     | key_len | ref             | rows     | Extra                    |
|    1 | SIMPLE      | pt1   | index  | PRIMARY,p_id  | p_id    | 100     | NULL            | 14170752 | Using where; Using index |
|    1 | SIMPLE      | pf1   | eq_ref | PRIMARY       | PRIMARY | 96      | fp1.pt1.p_id    |        1 | Using index              |
2 rows in set (0.00 sec)

配置文件

MariaDB [fp1]> show profile;
+------------------------------+-----------+
| Status                       | Duration  |
+------------------------------+-----------+
| Waiting for query cache lock |  0.000004 |
| Sending data                 |  0.003548 |
| Waiting for query cache lock |  0.000004 |
| Sending data                 | 57.530804 |
| end                          |  0.000015 |
| query end                    |  0.000006 |
| closing tables               |  0.000004 |
| Unlocking tables             |  0.000010 |
| freeing items                |  0.000009 |
| updating status              |  0.000044 |
| cleaning up                  |  0.000005 |
+------------------------------+-----------+
100 rows in set (0.02 sec)

扩展资料

MariaDB [fp1]> show profile cpu, block io, swaps for query 1;
| Status                       | Duration  | CPU_user  | CPU_system | Block_ops_in | Block_ops_out | Swaps |
| Sending data                 |  0.003303 |  0.000000 |   0.000000 |0 |             0 |  NULL |
| Waiting for query cache lock |  0.000003 |  0.000000 |   0.000000 |0 |             0 |  NULL |
| Sending data                 | 57.530804 | 56.690763 |   0.670804 |0 |             0 |  NULL |
| end                          |  0.000015 |  0.000000 |   0.000000 |0 |             0 |  NULL |
| query end                    |  0.000006 |  0.000000 |   0.000000 |0 |             0 |  NULL |
| closing tables               |  0.000004 |  0.000000 |   0.000000 |0 |             0 |  NULL |
| Unlocking tables             |  0.000010 |  0.000000 |   0.000000 |0 |             0 |  NULL |
| freeing items                |  0.000009 |  0.000000 |   0.000000 |0 |             0 |  NULL |
| updating status              |  0.000044 |  0.000000 |   0.000000 |0 |             0 |  NULL |
| cleaning up                  |  0.000005 |  0.000000 |   0.000000 |0 |             0 |  NULL |
100 rows in set (0.00 sec)

注意:由于stackoverflow输入限制的限制,我不得不从show profile输出中删除一些行(包含发送数据状态的时间,以毫秒为单位)。

再次感谢大家花时间研究问题,提供建议/意见。

0 个答案:

没有答案