簡體   English   中英

MySQL特定的查詢性能調優

[英]MySQL specific query performance tuning

我的MySQL查詢性能有問題。

表(InnoDB):

+--------------------+---------------------+------+-----+-------------------+-------+
| Field              | Type                | Null | Key | Default           | Extra |
+--------------------+---------------------+------+-----+-------------------+-------+
| st_resource_id     | varchar(32)         | NO   | MUL | NULL              |       |
| st_sub_resource_id | varchar(32)         | YES  |     | NULL              |       |
| st_title           | varchar(500)        | YES  |     | NULL              |       |
| st_resource_type   | varchar(100)        | NO   | MUL | NULL              |       |
| st_site_id         | tinyint(4)          | NO   | MUL | NULL              |       |
| st_time            | timestamp           | NO   | MUL | CURRENT_TIMESTAMP |       |
| st_user_id         | int(10) unsigned    | YES  |     | NULL              |       |
| st_full_access     | tinyint(1) unsigned | YES  |     | NULL              |       |
+--------------------+---------------------+------+-----+-------------------+-------+

索引:

+---------------+------------+------------------+--------------+--------------------+-----------+-------------+----------+--------+------+------------+---------+
| Table         | Non_unique | Key_name         | Seq_in_index | Column_name        | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+---------------+------------+------------------+--------------+--------------------+-----------+-------------+----------+--------+------+------------+---------+
| nr_statistics |          1 | resource_id      |            1 | st_resource_id     | A         |     1546165 |     NULL | NULL   |      | BTREE      |         |
| nr_statistics |          1 | resource_id      |            2 | st_sub_resource_id | A         |     1546165 |     NULL | NULL   | YES  | BTREE      |         |
| nr_statistics |          1 | st_time          |            1 | st_time            | A         |     1546165 |     NULL | NULL   |      | BTREE      |         |
| nr_statistics |          1 | st_site_id       |            1 | st_site_id         | A         |          16 |     NULL | NULL   |      | BTREE      |         |
| nr_statistics |          1 | st_resource_type |            1 | st_resource_type   | A         |          16 |       10 | NULL   |      | BTREE      |         |
+---------------+------------+------------------+--------------+--------------------+-----------+-------------+----------+--------+------+------------+---------+

查詢:

SELECT st_resource_id AS docId, count(*) AS cnt
FROM nr_statistics
WHERE
  st_resource_type = 'document'
  AND st_sub_resource_id = 'text'
  AND st_time > DATE_SUB(NOW(), INTERVAL 7 DAY)
  AND st_site_id = 1
GROUP BY st_resource_id
ORDER BY cnt DESC
LIMIT 0, 5;

查詢計划:

+----+-------------+---------------+-------+-------------------------------------+-------------+---------+------+---------+----------------------------------------------+
| id | select_type | table         | type  | possible_keys                       | key         | key_len | ref  | rows    | Extra                                        |
+----+-------------+---------------+-------+-------------------------------------+-------------+---------+------+---------+----------------------------------------------+
|  1 | SIMPLE      | nr_statistics | index | st_time,st_site_id,st_resource_type | resource_id | 197     | NULL | 1581044 | Using where; Using temporary; Using filesort |
+----+-------------+---------------+-------+-------------------------------------+-------------+---------+------+---------+----------------------------------------------+

表有~1,666,383行。 查詢運行速度非常慢。 在MySQL進程列表中,我在“復制到tmp表階段”中看到這個查詢很長一段時間(> 1分鍾)。 查詢會產生大量I / O負載。 我無法理解如何解決問題並加快查詢執行速度。

如果問題是錯誤索引的結果,那么哪些索引會正確?

UPD。 我創建了新的復合索引:

| nr_statistics |          1 | st_site_id_2     |            1 | st_site_id         | A         |          16 |     NULL | NULL   |      | BTREE      |         |
| nr_statistics |          1 | st_site_id_2     |            2 | st_resource_type   | A         |          16 |     NULL | NULL   |      | BTREE      |         |
| nr_statistics |          1 | st_site_id_2     |            3 | st_sub_resource_id | A         |      752018 |     NULL | NULL   | YES  | BTREE      |         |
| nr_statistics |          1 | st_site_id_2     |            4 | st_time            | A         |     1504037 |     NULL | NULL   |      | BTREE      |         |
| nr_statistics |          1 | st_site_id_2     |            5 | st_resource_id     | A         |     1504037 |     NULL | NULL   |      | BTREE      |         |

現在查詢計划是:

+----+-------------+---------------+-------+---------------+--------------+---------+------+-------+-----------------------------------------------------------+
| id | select_type | table         | type  | possible_keys | key          | key_len | ref  | rows  | Extra                                                     |
+----+-------------+---------------+-------+---------------+--------------+---------+------+-------+-----------------------------------------------------------+
|  1 | SIMPLE      | nr_statistics | range | st_site_id_2  | st_site_id_2 | 406     | NULL | 21168 | Using where; Using index; Using temporary; Using filesort |
+----+-------------+---------------+-------+---------------+--------------+---------+------+-------+-----------------------------------------------------------+

查詢現在運行速度非常快(為0.0x秒),但我必須強制使用新索引:

SELECT st_resource_id as docId, count( * ) AS Cnt
FROM nr_statistics
USE INDEX (st_site_id_2)
WHERE st_resource_type = 'document'
AND st_sub_resource_id = 'text'
AND st_time > DATE_SUB( NOW( ) , INTERVAL 7 DAY )
AND st_site_id = 1
GROUP BY st_resource_id
ORDER BY cnt DESC
LIMIT 0 , 5;

雖然問題得到了解決(不是很漂亮但有效的方式),但我仍然有一些懸而未決的問題(見評論)。

(st_site_id, st_resource_type, st_sub_resourse_id, st_time, st_resource_id)上創建復合索引。

但是,你仍然有temporaryfilesort的計划,因為您訂購的COUNT(*)這是不可轉位。

如果您需要快速且經常地運行此查詢,則必須創建一個聚合表,該表將存儲每個站點/資源/子課程/周組合的計數,並在觸發器中更新它。

您是否嘗試在st_resource_type, st_resource_id, st_time and st_site_id上創建復合索引? 它看起來像你有幾個索引,但大多數是在一列,或可能是2列。 通過使用您需要的更多列的復合索引,可以提高性能。

在使用多個where子句進行查詢時,編寫它們的順序應與編寫查詢的順序相匹配。

在您的特定情況下,它將是:

CREATE INDEX stats_index ON nr_statistics (st_resource_type, st_sub_resource_id, st_time, st_site_id);

這應該會給你一個非常好的速度提升。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM