MySQL查询性能 - 查询/架构/索引?

Rya*_*yan 6 mysql sql performance

基本上有一些查询的性能问题,主要是我最大的表,其中包含调用数据.

主查询包含相当多的左连接和子选择,但在我正在运行查询的情况下,我希望返回1.3M调用,查询只是没有这样做.必须在7分钟停止它意味着某处肯定存在问题.

我缩小了主查询并测试了最简单的子选择连接

SELECT
    DateStart,
    ID,
    NumbID,
    EffectiveFlag,
    OrigNumber
FROM calls
WHERE 
    DateStart <= '2013-12-31'
AND DateStart >= '2013-01-01'
AND CallLength >= '00:00:00' 
AND Direction = '1'
AND CustID IN (474,482,250,268,197,604,132,359,279,441,118,448,152,133,380,162,249,679,226,259,2450,2408,2451,2453,2439,2454,2444,2445,2452)
Run Code Online (Sandbox Code Playgroud)

甚至该查询需要4.5s - 因此当它是具有其他连接和子选择的查询中的子选择时,我可以想象为什么整个查询不可用.

上述查询的解释声明是

+----+-------------+-------+-------+-------------------------------------------------------------------------------------------------------+----------------------+---------+------+---------+-------------+
| id | select_type | table | type  | possible_keys                                                                                         | key                  | key_len | ref  | rows    | Extra       |
+----+-------------+-------+-------+-------------------------------------------------------------------------------------------------------+----------------------+---------+------+---------+-------------+
|  1 | SIMPLE      | calls | range | idx_CustID,idx_DateStart,idx_CustID_DateStart,idx_CustID_TermNumber,idx_Direction                     | idx_CustID_DateStart | 7       | NULL | 1660009 | Using where |
+----+-------------+-------+-------+-------------------------------------------------------------------------------------------------------+----------------------+---------+------+---------+-------------+
Run Code Online (Sandbox Code Playgroud)

调用表的数据库模式是

+-------------------+-------------+------+-----+---------------------+----------------+
| Field             | Type        | Null | Key | Default             | Extra          |
+-------------------+-------------+------+-----+---------------------+----------------+
| ID                | int(11)     | NO   | PRI | NULL                | auto_increment |
| CustID            | int(11)     | NO   | MUL | 0                   |                |
| CarrID            | int(11)     | NO   | MUL | NULL                |                |
| TariID            | int(11)     | NO   | MUL | 0                   |                |
| CarrierRef        | varchar(30) | NO   | MUL |                     |                |
| NumbID            | int(11)     | NO   | MUL | 0                   |                |
| VlviID            | int(11)     | NO   | MUL | NULL                |                |
| VcamID            | int(11)     | NO   | MUL | NULL                |                |
| SomeID            | int(11)     | NO   | MUL | NULL                |                |
| VlnsID            | int(11)     | NO   | MUL | NULL                |                |
| NGNumber          | varchar(12) | NO   |     |                     |                |
| OrigNumber        | varchar(16) | NO   | MUL | NULL                |                |
| CLIRestrictedFlag | int(2)      | NO   |     | NULL                |                |
| OrigLocality      | varchar(11) | NO   | MUL |                     |                |
| OrigAreaCode      | varchar(11) | NO   | MUL |                     |                |
| TermNumber        | varchar(16) | NO   | MUL | NULL                |                |
| BatchNumber       | varchar(10) | NO   | MUL |                     |                |
| DateStart         | date        | NO   | MUL | 0000-00-00          |                |
| DateClear         | date        | NO   |     | 0000-00-00          |                |
| TimeStart         | time        | NO   |     | 00:00:00            |                |
| TimeClear         | time        | NO   |     | 00:00:00            |                |
| CallLength        | time        | NO   |     | 00:00:00            |                |
| RingLength        | time        | NO   |     | 00:00:00            |                |
| EffectiveFlag     | smallint(1) | NO   | MUL | NULL                |                |
| UnansweredFlag    | smallint(1) | NO   | MUL | NULL                |                |
| EngagedFlag       | smallint(1) | NO   |     | NULL                |                |
| RecID             | int(11)     | NO   | MUL | NULL                |                |
| CreatedUserID     | int(11)     | NO   |     | 0                   |                |
| CreatedDatetime   | datetime    | NO   | MUL | 0000-00-00 00:00:00 |                |
| Direction         | int(1)      | NO   | MUL | NULL                |                |
+-------------------+-------------+------+-----+---------------------+----------------+
Run Code Online (Sandbox Code Playgroud)

调用表上的索引是

+-------+------------+---------------------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name                  | Seq_in_index | Column_name     | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+---------------------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+
| calls |          0 | PRIMARY                   |            1 | ID              | A         |    23905312 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_CustID                |            1 | CustID          | A         |        1685 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_NumbID                |            1 | NumbID          | A         |       37765 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_OrigNumber            |            1 | OrigNumber      | A         |     5976328 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_OrigLocality          |            1 | OrigLocality    | A         |       45019 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_OrigAreaCode          |            1 | OrigAreaCode    | A         |         846 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_TermNumber            |            1 | TermNumber      | A         |      232090 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_DateStart             |            1 | DateStart       | A         |        4596 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_EffectiveFlag         |            1 | EffectiveFlag   | A         |           2 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_UnansweredFlag        |            1 | UnansweredFlag  | A         |           2 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_EngagedFlag           |            1 | UnansweredFlag  | A         |           2 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_TariID                |            1 | TariID          | A         |         110 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_CustID_DateStart      |            1 | CustID          | A         |        1685 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_CustID_DateStart      |            2 | DateStart       | A         |      919435 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_NumbID_DateStart      |            1 | NumbID          | A         |       37765 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_NumbID_DateStart      |            2 | DateStart       | A         |     5976328 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_RecID                 |            1 | RecID           | A         |      288015 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_CarrierRef            |            1 | CarrierRef      | A         |     7968437 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_CustID_CallTermNumber |            1 | CustID          | A         |        1685 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_CustID_CallTermNumber |            2 | TermNumber      | A         |      246446 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_CreatedDatetime       |            1 | CreatedDatetime | A         |      771139 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_Direction             |            1 | Direction       | A         |           2 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_VlviID                |            1 | VlviID          | A         |       50539 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_SomeID                |            1 | SomeID          | A         |          30 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_VcamID                |            1 | VcamID          | A         |          64 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_VlnsID                |            1 | VlnsID          | A         |         191 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_CarrID                |            1 | CarrID          | A         |           4 |     NULL | NULL   |      | BTREE      |         |
| calls |          1 | idx_BatchNumber           |            1 | BatchNumber     | A         |      271651 |     NULL | NULL   |      | BTREE      |         |
+-------+------------+---------------------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+
Run Code Online (Sandbox Code Playgroud)

我理解的东西可能导致性能,是具有低基数的列上的索引.我知道诸如Direction这样的基数为2的基数实际上可能更糟糕的是在性能方面有一个索引,但仅此一点不应该使语句变得如此缓慢.

就具有有价值索引的基数要求而言,与总表记录相比,是否存在一般基数百分比,其中索引会提高性能并且会降低性能?

我知道没有人能够向我提出一个将查询时间从4.5s更改为0.01s的答案,但对查询本身,表模式,索引或硬件的任何建议都是非常感激.

更新:

@Sebas"请你重新运行查询并解释没有零件的计划:AND CallLength> = '00:00:00'AND Direction ='1'please?"

+----+-------------+-------+-------+---------------------------------------------------------------------+----------------------+---------+------+--------+-------------+
| id | select_type | table | type  | possible_keys                                                       | key                  | key_len | ref  | rows   | Extra       |
+----+-------------+-------+-------+---------------------------------------------------------------------+----------------------+---------+------+--------+-------------+
|  1 | SIMPLE      | calls | range | idx_CustID,idx_DateStart,idx_CustID_DateStart,idx_CustID_TermNumber | idx_CustID_DateStart | 7       | NULL | 724813 | Using where |
+----+-------------+-------+-------+---------------------------------------------------------------------+----------------------+---------+------+--------+-------------+
Run Code Online (Sandbox Code Playgroud)

Max*_*sky 1

你的索引太多了。例如,您不需要单独的 CustID 索引,因为它位于 CustID,DateStart 中的最左侧。您在 UnansweredFlag 上有 2 个索引。您真的需要所有这些索引吗?这不仅会减慢插入/更新速度,还会减慢优化器速度,并可能欺骗优化器选择不太好的索引。

现在,关于具体查询。您需要查看哪个字段或组合对查询限制最大(因为现在它扫描 160 万行!)并强制它使用该索引。因此,使用指定的 DateStart 对每个 where 子句(方向、调用长度)运行 SELECT COUNT(*) 查询(您始终希望基于此进行限制)。也许您只需要向索引添加方向即可。

另外,在MySQL 5.6之前,WHERE子句中的子查询没有优化,所以也许你应该重写整个查询以使用join而不是subselect,而不是优化特定的查询