MySQL:如何优化此查询

时间:2016-03-09 21:25:38

标签: mysql optimization indexing view explain

我希望减少在视图中查询数据的时间。

我的表格有以下结构:

Rings包含单个响铃,每个响铃都具有ID_RingTypeNumber的唯一组合,但也包含ID,在其他位置用作外键。

-- RINGS
CREATE TABLE `Rings` (
    ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    ID_RingType CHAR(2) NOT NULL,
    Number MEDIUMINT UNSIGNED NOT NULL,
    ID_RingStatus TINYINT DEFAULT 1,
    ID_User INT(11),
    DateLastChange TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

    FOREIGN KEY (ID_RingType) REFERENCES RingType(Code),
    FOREIGN KEY (ID_RingStatus) REFERENCES RingStatus(ID),
    FOREIGN KEY (ID_User) REFERENCES `848-cso`.`Users`(UID)
);
-- create index on tripple ID_User, ID_RingType, Number
CREATE INDEX idx_rings ON `Rings` (ID_User, ID_RingType, Number);
CREATE INDEX idx_rings_overview ON `Rings` (ID_RingType, Number, ID_RingStatus);
CREATE INDEX idx_rings_numbers ON `Rings` (ID_RingStatus, ID_User, ID_RingType, Number);

响铃状态仅包含4个值及其含义

-- RING STATUS
CREATE TABLE `RingStatus` (
    ID TINYINT NOT NULL PRIMARY KEY,
    Name VARCHAR(20) UNIQUE COLLATE utf8_czech_ci,
    NameEng VARCHAR(20)
);

响铃类型由两个字母代码

标识
-- RING TYPE
CREATE TABLE `RingType` (
    Code CHAR(2) NOT NULL PRIMARY KEY,
    Material VARCHAR(30) COLLATE utf8_czech_ci,
    Radius DOUBLE UNSIGNED,
    MaxVal MEDIUMINT UNSIGNED NOT NULL
);

此外,我使用以下功能:

/*
Function returns tinyint(1) specifying, whether ring was assigned
*/
CREATE FUNCTION fn_isRingAssigned (idRingStatus TINYINT)
RETURNS TINYINT(1) DETERMINISTIC
RETURN IF(idRingStatus = 1,1,2);

我尝试优化的查询存储在以下VIEW

/*
View finds contiguous ranges of rings grouped by type, radius and status
*/
ALTER VIEW vw_rings_overview AS SELECT 
    a.ID_RingType, 
    rt.Radius,
    fn_isRingAssigned(a.ID_RingStatus) AS status,
    rs.Name,
    a.Number        AS min,
    MIN(b.Number)   AS max
FROM
  RingStatus AS rs, Rings AS a
  JOIN RingType AS rt ON a.ID_RingType = rt.Code
  JOIN Rings AS b 
    ON  a.ID_RingType = b.ID_RingType 
    AND fn_isRingAssigned(a.ID_RingStatus) = fn_isRingAssigned(b.ID_RingStatus)
    AND a.Number <= b.Number 
WHERE NOT EXISTS
      ( SELECT 1 
        FROM Rings AS c 
        WHERE c.ID_RingType = a.ID_RingType 
          AND fn_isRingAssigned(c.ID_RingStatus) = fn_isRingAssigned(a.ID_RingStatus)
          AND c.Number = a.Number - 1
      )
  AND NOT EXISTS 
      ( SELECT 1 
        FROM Rings AS d 
        WHERE d.ID_RingType = b.ID_RingType 
          AND fn_isRingAssigned(d.ID_RingStatus) = fn_isRingAssigned(b.ID_RingStatus)
          AND d.Number = b.Number + 1
      ) 
  AND fn_isRingAssigned(a.ID_RingStatus) = rs.ID
GROUP BY 
    a.ID_RingType, 
    fn_isRingAssigned(a.ID_RingStatus),
    a.Number 
ORDER BY 
    a.ID_RingType,
    a.Number;

Rings表中的数据如下所示

+----+-------------+--------+---------------+---------+---------------------+
| ID | ID_RingType | Number | ID_RingStatus | ID_User | DateLastChange      |
+----+-------------+--------+---------------+---------+---------------------+
|  1 | A           |      1 |             4 |       2 | 2015-12-02 19:02:50 |
|  2 | A           |      2 |             4 |       2 | 2015-12-02 19:02:56 |
|  3 | A           |      3 |             4 |       2 | 2015-12-02 19:22:29 |
|  4 | A           |      4 |             4 |       2 | 2015-12-21 20:32:24 |
|  5 | A           |      5 |             4 |       2 | 2015-12-21 20:52:08 |
|  6 | A           |      6 |             4 |       2 | 2015-12-21 20:52:22 |
|  7 | A           |      7 |             1 |       2 | 2015-12-02 19:00:23 |
|  8 | A           |      8 |             1 |       2 | 2015-12-02 19:00:23 |
|  9 | A           |      9 |             1 |       2 | 2015-12-02 19:00:23 |
| 10 | A           |     10 |             1 |       2 | 2015-12-02 19:00:23 |
+----+-------------+--------+---------------+---------+---------------------+

查询结果如下:

mysql> select * from vw_rings_overview;
+-------------+--------+--------+----------------+-----+-------+
| ID_RingType | Radius | status | Name           | min | max   |
+-------------+--------+--------+----------------+-----+-------+
| A           |     20 |      2 | Assigned       |   1 |   6   |
| A           |     20 |      1 | Not assigned   |   7 |  10   |
+-------------+--------+--------+----------------+-------------+

视图的作用是在环中找到连续的范围,具有相同的环类型,状态和半径。

Rings目前包含少于30 000行,查询大约需要3 000行。 2秒。它预计包含数百万行,所以我希望优化表,索引和视图的设计。

以下是EXPLAIN

的结果
mysql> explain select * from vw_rings_overview;
+----+--------------------+------------+--------+--------------------+--------------------+---------+-----------------------------+-------+-----------------------------------------------------------+
| id | select_type        | table      | type   | possible_keys      | key                | key_len | ref                         | rows  | Extra                                                     |
+----+--------------------+------------+--------+--------------------+--------------------+---------+-----------------------------+-------+-----------------------------------------------------------+
|  1 | PRIMARY            | <derived2> | ALL    | NULL               | NULL               | NULL    | NULL                        |    19 |                                                           |
|  2 | DERIVED            | a          | index  | idx_rings_overview | idx_rings_overview | 7       | NULL                        | 25173 | Using where; Using index; Using temporary; Using filesort |
|  2 | DERIVED            | rt         | eq_ref | PRIMARY            | PRIMARY            | 2       | 848-avi2.a.ID_RingType      |     1 |                                                           |
|  2 | DERIVED            | rs         | eq_ref | PRIMARY            | PRIMARY            | 1       | func                        |     1 | Using where                                               |
|  2 | DERIVED            | b          | ref    | idx_rings_overview | idx_rings_overview | 2       | 848-avi2.rt.Code            |  1573 | Using where; Using index                                  |
|  4 | DEPENDENT SUBQUERY | d          | ref    | idx_rings_overview | idx_rings_overview | 5       | 848-avi2.b.ID_RingType,func |     1 | Using where; Using index                                  |
|  3 | DEPENDENT SUBQUERY | c          | ref    | idx_rings_overview | idx_rings_overview | 5       | 848-avi2.a.ID_RingType,func |     1 | Using where; Using index                                  |
+----+--------------------+------------+--------+--------------------+--------------------+---------+-----------------------------+-------+-----------------------------------------------------------+

以下是一些示例数据:http://sqlfiddle.com/#!9/b8b489/1

0 个答案:

没有答案