高性能查询可计算多对多数据

时间:2019-02-25 12:10:02

标签: mysql sql query-optimization

请求表:

requests
    +id (INT) AUTO_INCREMENT
    +title (VARCHAR)

状态表:

statuses
    +id (INT) AUTO_INCREMENT
    +title (VARCHAR)

关系表:

request_status (MANY TO MANY)
    +id (INT) AUTO_INCREMENT
    +request_id (INT) Foreign Key
    +status_id (INT)

我只想统计当前 status_id为2 的那些请求。当前请求的状态(status_id)是request_status表中的最后一个。

如果数据约为1600k,那将是完美的高性能查询

3 个答案:

答案 0 :(得分:1)

假设最新状态是ID最大的状态:

SELECT COUNT(*)
FROM request_status
WHERE status_id = 2
AND NOT EXISTS (
    SELECT 1
    FROM request_status AS x
    WHERE request_id = request_status.request_id
    AND id > request_status.id
)

或者这个:

SELECT COUNT(*)
FROM (
    SELECT 1
    FROM request_status
    GROUP BY request_id
    HAVING MAX(CASE WHEN status_id = 2 THEN id END) = MAX(id)
) AS x

您将需要一些索引。我建议创建这些:

KEY ix1 (request_id, status_id)
KEY ix2 (status_id,  request_id)

答案 1 :(得分:0)

SELECT COUNT(*) FROM request_status WHERE status_id = 2;

如果我正确理解了您的问题,该方法应该最好地工作-应该计算status_id等于2的对。

答案 2 :(得分:0)

关系表的架构效率低下。我将与他们讨论here

但是,相反,让我们更改架构以使其更加高效。而不是3个具有多对多映射的表,而只有一个表:

CREATE TABLE requests (
    id ...,
    latest_status  ENUM('eating', 'sleeping', 'running'),
    all_statuses    SET('eating', 'sleeping', 'running'),
) ENGINE=InnoDB;

(或者,您可以使用TINYINTs,但使用不同的语法。)

给定request的状态更改时,请设置latest_status并将新状态“或”设置为all_statuses

要检查最新的runningWHERE latest_status = 'running'

或者,如果使用某些数值:WHERE latest_status = 2