Mysql 查询时间太长

Mysql 查询时间太长,mysql,database,indexing,rdbms,Mysql,Database,Indexing,Rdbms,我有以下问题: SELECT * FROM document d INNER JOIN users_documents ud ON d.id = ud.document_id WHERE (d.document_state_id=2 AND ud.sharing_type_id=1 AND ud.user_id=:id AND CURRENT_TIMESTAMP() BETWEEN d.upload_datetime AND d.approval_en

我有以下问题:

SELECT *
FROM document d
INNER JOIN users_documents ud ON d.id = ud.document_id 
WHERE (d.document_state_id=2
       AND ud.sharing_type_id=1
       AND ud.user_id=:id
       AND CURRENT_TIMESTAMP() BETWEEN d.upload_datetime AND d.approval_end_time
       AND ud.approval=2)
OR(d.document_state_id=1
   AND ud.sharing_type_id=2
   AND ud.user_id=:id
   AND CURRENT_TIMESTAMP() BETWEEN d.active_start_time AND d.active_end_time 
   AND ud.approval=2)
ORDER BY ud.application_date;
问题是,当我将查询结束更改为:

ORDER BY ud.uploadDatetime;
我添加了索引:upload_datetime(table document),现在查询大约需要70毫秒。问题是我确实需要根据ud.application_date对数据进行排序。 我试图添加一个索引:application\u date(在表users\u文档上),但没有帮助(仍然需要800毫秒)。这次我应该使用哪个指数来降低价格?或者我该怎么办?我正在使用MySQL

非常感谢你的帮助

编辑: 查询说明:查询为给定用户返回具有某个id的新单据,返回“审批”(共享类型=1)和读取(共享类型=2)单据,审批=2(用户未看到该单据),审批=1(用户审批该单据),0=不批准;upload_datetime=文件上传到系统的时间戳;审批人\结束\时间=单据在此日期前可供用户审批;activeStartTime=批准后,文档将从此日期(=activeEndTime)起显示给其他用户。 结构

-- -----------------------------------------------------
-- Table `po_db`.`document_state`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `po_db`.`document_state` (
  `id` BIGINT(20) NOT NULL,
  `state` VARCHAR(255) NULL DEFAULT NULL,
  PRIMARY KEY (`id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8mb4
COLLATE = utf8mb4_0900_ai_ci;

-- -----------------------------------------------------
-- Table `po_db`.`document`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `po_db`.`document` (
  `id` BIGINT(20) NOT NULL,
  `active_end_time` DATETIME NOT NULL,
  `active_start_time` DATETIME NOT NULL,
  `approval_end_time` DATETIME NOT NULL,
  `description` VARCHAR(255) NOT NULL,
  `name` VARCHAR(60) NOT NULL,
  `resource_path` VARCHAR(255) NOT NULL,
  `title` VARCHAR(15) NOT NULL,
  `upload_datetime` DATETIME NOT NULL,
  `document_state_id` BIGINT(20) NOT NULL,
  `user_id` BIGINT(20) NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE INDEX `UK_36vs45u76s1n950kwxfa5lyhc` (`name` ASC),
  INDEX `FK1rwpvwxw2bvldt30kwfcbf57l` (`document_state_id` ASC),
  INDEX `FKjhdxdv9sijhujiynqbb5jc010` (`user_id` ASC),
  INDEX `title` (`title` ASC),
  INDEX `upload` USING BTREE (`upload_datetime`),
  CONSTRAINT `FK1rwpvwxw2bvldt30kwfcbf57l`
    FOREIGN KEY (`document_state_id`)
    REFERENCES `po_db`.`document_state` (`id`),
  CONSTRAINT `FKjhdxdv9sijhujiynqbb5jc010`
    FOREIGN KEY (`user_id`)
    REFERENCES `po_db`.`user` (`id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8mb4
COLLATE = utf8mb4_0900_ai_ci;


-- -----------------------------------------------------
-- Table `po_db`.`sharing_type`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `po_db`.`sharing_type` (
  `id` BIGINT(20) NOT NULL,
  `name` VARCHAR(255) NULL DEFAULT NULL,
  PRIMARY KEY (`id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8mb4
COLLATE = utf8mb4_0900_ai_ci;

编辑2: 我将查询的结尾更改为:

ORDER BY CASE WHEN d.document_state_id=2 THEN d.upload_datetime ELSE d.active_start_time END;
它基本上与application_date相同,但速度仍然很慢(300毫秒,但优于800毫秒)

我试图添加索引(表文档):
document\u state\u id、upload\u datetime、active\u start\u time


但这一点也没有帮助…:/

计划A:
变为
联合体

    ( SELECT  *
            FROM  document d
            INNER JOIN  users_documents ud  ON d.id = ud.document_id
            WHERE  d.document_state_id=2
              AND  ud.sharing_type_id=1
              AND  ud.user_id=:id
              AND  CURRENT_TIMESTAMP() BETWEEN d.upload_datetime
                                           AND d.approval_end_time
              AND  ud.approval=2
    )
    UNION ALL
    ( SELECT  *
            FROM  document d
            INNER JOIN  users_documents ud  ON d.id = ud.document_id
            WHERE  d.document_state_id=1
              AND  ud.sharing_type_id=2
              AND  ud.user_id=:id
              AND  CURRENT_TIMESTAMP() BETWEEN d.active_start_time
                                           AND d.active_end_time
              AND  ud.approval=2 
    )
    ORDER BY  application_date;
这样,每次选择都可以很好地利用从approval ASC、Shared\u type\u id ASC、user\u id ASC开始的索引。(第4列没有帮助。)

方案B:使用“覆盖指数”:

加上这些新指标,;顺序很重要:

UD: INDEX(approval, sharing_type_id, user_id, document_id)  -- document_id last
D: INDEX(document_state_id, approval_end_time, approval_start_time, document_id)
D: INDEX(document_state_id, active_end_time, active_start_time, document_id)

如果您为
文档.upload\u datetime
添加了索引,那么为
文档.approval\u end\u time
添加索引也是有意义的。我怀疑瓶颈是
current\u timestamp()
函数,它可能会对每一行执行,也可能会对所有相关的表执行SHOW CREATE TABLE语句,有关查询性能的问题总是需要对给定的query@Strawberry已添加结构。通过执行“解释[您的查询]”找到解释“每张表有多少行?”谢谢你的回答。不幸的是,我不能在我的查询中使用UNION,因为JPA是必需的,而且它不支持UNION:(我在MySQL workbench中尝试了这个查询,我得到了这个错误:错误代码:1250。来自其中一个SELECTs的表“ud”不能在全局顺序子句中使用。你知道如何消除这个错误吗?@Sirdhemond-修复了2个拼写错误
SELECT d2.*, ud2.*
  FROM (
    ( SELECT  id, document_id, sharing_type_id, user_id
            FROM  document d
            INNER JOIN  users_documents ud  ON d.id = ud.document_id
            WHERE  d.document_state_id=2
              AND  ud.sharing_type_id=1
              AND  ud.user_id=:id
              AND  CURRENT_TIMESTAMP() BETWEEN d.upload_datetime 
                                           AND d.approval_end_time
              AND  ud.approval=2
    )
    UNION ALL
    ( SELECT  id, document_id, sharing_type_id, user_id
            FROM  document d
            INNER JOIN  users_documents ud  ON d.id = ud.document_id
            WHERE  d.document_state_id=1
              AND  ud.sharing_type_id=2
              AND  ud.user_id=:id
              AND  CURRENT_TIMESTAMP() BETWEEN d.active_start_time
                                           AND d.active_end_time
              AND  ud.approval=2 
    )
       )
  JOIN document d2  USING(id)
  JOIN users_documents ud2  USING(document_id, sharing_type_id, user_id)
  ORDER BY  ud2.application_date;
UD: INDEX(approval, sharing_type_id, user_id, document_id)  -- document_id last
D: INDEX(document_state_id, approval_end_time, approval_start_time, document_id)
D: INDEX(document_state_id, active_end_time, active_start_time, document_id)