优化了SQL查询在总表包含10M记录时加载结果

问题描述 投票:0回答:1
SELECT 
    d.USPS_IMB AS IMb,
    d.CorrelationId,
    d.EINNo AS EIN,
    d.UniqueFormId AS FormId,
    d.ProductionFacility AS Facility,
    CASE 
        WHEN d.ProductionStatusNo < 5 THEN 'Received'
        WHEN d.ProductionStatusNo = 5 THEN 'Printed'
        WHEN d.ProductionStatusNo = 6 THEN 'Folded / Sealed'
        WHEN d.ProductionStatusNo = 7 THEN 'Mailed'
        ELSE 'Unknown'
    END AS Status,
    d.StatusDateTime AS StatusDateUTC
FROM detail d
JOIN (
    SELECT 
        UniqueFormId,
        MAX(ProductionStatusNo) AS MaxProductionStatusNo
    FROM detail
    WHERE ProductionFacility='MAIL'
    GROUP BY UniqueFormId
) AS maxStatus
ON d.UniqueFormId = maxStatus.UniqueFormId AND d.ProductionStatusNo = maxStatus.MaxProductionStatusNo
WHERE d.ProductionFacility='MAIL';

我对详细表有上述查询,目前我在 UniqueFormId、生产设施以及 ProductionStatusNo 上都有索引。

我需要建议来提高此查询的性能,以便可以加载结果。

CREATE TABLE `detail` (
  `Id` int NOT NULL AUTO_INCREMENT,
 
  `EINNo` varchar(45) NOT NULL,
  `EmployeeNo` varchar(45) NOT NULL,
  `Form` varchar(45) NOT NULL,
  `ProductionStatus` varchar(45) NOT NULL,
  `ProductionStatusNo` int NOT NULL,
  
  `StatusDateTime` datetime DEFAULT NULL,
 
  `UniqueFormId` varchar(450) NOT NULL,
  `ProductionFacility` varchar(450) NOT NULL,
  
  `USPS_IMB` varchar(45) DEFAULT NULL,
  `StatusDate` date DEFAULT NULL
 
  PRIMARY KEY (`Id`,`ProductionStatusNo`),
  KEY `idx_detail_EINNo` (`EINNo`),
  KEY `idx_detail_EmployeeNo` (`EmployeeNo`),
  KEY `idx_detail_Form` (`Form`),
  KEY `idx_detail_UniqueFormId` (`UniqueFormId`),
  KEY `idx_detail_ProductionFacility` (`ProductionFacility`),
  KEY `idx_detail_ProductionStatusNo` (`ProductionStatusNo`),
  KEY `idx_detail_StatusDate` (`StatusDate`),
  
  KEY `idx_detail_PackageReference2` (`PackageReference2`),
  KEY `idx_detail_CartonID` (`CartonID`)
) ENGINE=InnoDB AUTO_INCREMENT=216695199 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
/*!50100 PARTITION BY RANGE (`ProductionStatusNo`)
(PARTITION p0 VALUES LESS THAN (1) ENGINE = InnoDB,
 PARTITION p1 VALUES LESS THAN (2) ENGINE = InnoDB,
 PARTITION p2 VALUES LESS THAN (3) ENGINE = InnoDB,
 PARTITION p3 VALUES LESS THAN (4) ENGINE = InnoDB,
 PARTITION p4 VALUES LESS THAN (5) ENGINE = InnoDB,
 PARTITION p5 VALUES LESS THAN (6) ENGINE = InnoDB,
 PARTITION p6 VALUES LESS THAN (7) ENGINE = InnoDB,
 PARTITION p7 VALUES LESS THAN (8) ENGINE = InnoDB,
 PARTITION p8 VALUES LESS THAN (9) ENGINE = InnoDB,
 PARTITION p9 VALUES LESS THAN (10) ENGINE = InnoDB,
 PARTITION p10 VALUES LESS THAN (11) ENGINE = InnoDB,
 PARTITION p11 VALUES LESS THAN (12) ENGINE = InnoDB,
 PARTITION p12 VALUES LESS THAN (13) ENGINE = InnoDB,
 PARTITION p13 VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */;
sql mysql optimization query-optimization
1个回答
0
投票

要优化您的 SQL 查询,您可以尝试以下操作:

创建复合索引:

CREATE INDEX idx_detail_facility_form_status ON detail (ProductionFacility, UniqueFormId, ProductionStatusNo);

可能使用

ProductionFacility
:

重新评估分区
ALTER TABLE detail
PARTITION BY RANGE (ProductionFacility) (
    PARTITION p0 VALUES LESS THAN ('A'),
    PARTITION p1 VALUES LESS THAN ('B'),
    -- add additional partitions as needed
);

优化子查询:

SELECT 
    UniqueFormId,
    MAX(ProductionStatusNo) AS MaxProductionStatusNo
FROM detail
WHERE ProductionFacility = 'MAIL'
GROUP BY UniqueFormId;

创建附加索引:

CREATE INDEX idx_detail_formid_status ON detail (UniqueFormId, ProductionStatusNo);

分析查询执行计划:

EXPLAIN SELECT 
    d.USPS_IMB AS IMb,
    d.CorrelationId,
    d.EINNo AS EIN,
    d.UniqueFormId AS FormId,
    d.ProductionFacility AS Facility,
    CASE 
        WHEN d.ProductionStatusNo < 5 THEN 'Received'
        WHEN d.ProductionStatusNo = 5 THEN 'Printed'
        WHEN d.ProductionStatusNo = 6 THEN 'Folded / Sealed'
        WHEN d.ProductionStatusNo = 7 THEN 'Mailed'
        ELSE 'Unknown'
    END AS Status,
    d.StatusDateTime AS StatusDateUTC
FROM detail d
JOIN (
    SELECT 
        UniqueFormId,
        MAX(ProductionStatusNo) AS MaxProductionStatusNo
    FROM detail
    WHERE ProductionFacility='MAIL'
    GROUP BY UniqueFormId
) AS maxStatus
ON d.UniqueFormId = maxStatus.UniqueFormId AND d.ProductionStatusNo = maxStatus.MaxProductionStatusNo
WHERE d.ProductionFacility='MAIL';

确保数据类型和架构得到优化,并执行定期维护任务,例如

ANALYZE TABLE
以保持统计数据最新。

© www.soinside.com 2019 - 2024. All rights reserved.