SQL 查询卡在统计状态

Posted

技术标签:

【中文标题】SQL 查询卡在统计状态【英文标题】:SQL Query Stuck in Statistics State 【发布时间】:2013-07-21 18:08:02 【问题描述】:

我今天一直在对这个复杂的查询进行故障排除,认为这是一个性能问题。查询似乎陷入了“统计”状态。它目前处于该状态 1300 秒。

我已经检查了相关表的索引——我已经优化了表——是什么导致了这个挂起?

SELECT
    Import_Values.id,
    Import_Values.part_id,
    Import_Values.qty,
    Import_Values.note,
    Parts.partterminologyname,
    GROUP_CONCAT(BaseVehicle.YearID, ' ', Make.MakeName, ' ', Model.modelname, ' ', SubModel.SubModelName SEPARATOR ', '),
    GROUP_CONCAT(DISTINCT(EngineDesignation.EngineDesignationName) SEPARATOR ', '),
    GROUP_CONCAT(DISTINCT(EngineVIN.EngineVINName) SEPARATOR ', '),
    GROUP_CONCAT(DISTINCT(EngineBase.Liter) SEPARATOR ', '),
    GROUP_CONCAT(DISTINCT(EngineBase.CC) SEPARATOR ', '),
    GROUP_CONCAT(DISTINCT(EngineBase.CID) SEPARATOR ', '),
    GROUP_CONCAT(DISTINCT(EngineBase.Cylinders) SEPARATOR ', '),
    GROUP_CONCAT(DISTINCT(EngineBase.BlockType) SEPARATOR ', '),
    GROUP_CONCAT(DISTINCT(EngineBase.EngBoreIn) SEPARATOR ', '),
    GROUP_CONCAT(DISTINCT(EngineBase.EngBoreMetric) SEPARATOR ', '),
    GROUP_CONCAT(DISTINCT(EngineBase.EngStrokeIn) SEPARATOR ', '),
    GROUP_CONCAT(DISTINCT(EngineBase.EngStrokeMetric) SEPARATOR ', '),
    GROUP_CONCAT(DISTINCT(FuelDeliveryType.FuelDeliveryTypeName) SEPARATOR ', '),
    GROUP_CONCAT(DISTINCT(FuelDeliverySubType.FuelDeliverySubTypeName) SEPARATOR ', '),
    GROUP_CONCAT(DISTINCT(FuelSystemControlType.FuelSystemControlTypeName) SEPARATOR ', '),
    GROUP_CONCAT(DISTINCT(FuelSystemDesign.FuelSystemDesignName) SEPARATOR ', '),
    GROUP_CONCAT(DISTINCT(Aspiration.AspirationName) SEPARATOR ', '),
    GROUP_CONCAT(DISTINCT(CylinderHeadType.CylinderHeadTypeName) SEPARATOR ', '),
    GROUP_CONCAT(DISTINCT(FuelType.FuelTypeName) SEPARATOR ', '),
    GROUP_CONCAT(DISTINCT(IgnitionSystemType.IgnitionSystemTypeName) SEPARATOR ', '),
    GROUP_CONCAT(DISTINCT(Mfr.MfrName) SEPARATOR ', '),
    GROUP_CONCAT(DISTINCT(EngineVersion.EngineVersion) SEPARATOR ', '),
    GROUP_CONCAT(DISTINCT(Valves.ValvesPerEngine) SEPARATOR ', '),
    GROUP_CONCAT(DISTINCT(BedLength.BedLength) SEPARATOR ', '),
    GROUP_CONCAT(DISTINCT(BedLength.BedLengthMetric) SEPARATOR ', ')
    FROM 
    Import_Values
    INNER JOIN BaseVehicle 
        ON Import_Values.base_vehicle_id=BaseVehicle.BaseVehicleID
    INNER JOIN Parts 
        ON Import_Values.part_type_id=Parts.PartTerminologyID
    INNER JOIN Make
        ON BaseVehicle.MakeID=Make.MakeID
    INNER JOIN Model
        ON BaseVehicle.ModelID=Model.ModelID
    INNER JOIN Vehicle
        ON Import_Values.base_vehicle_id=Vehicle.BaseVehicleID
    INNER JOIN SubModel
        ON Vehicle.SubModelID=SubModel.SubModelID
    INNER JOIN VehicleToEngineConfig
        ON Vehicle.VehicleID=VehicleToEngineConfig.VehicleID
    INNER JOIN EngineConfig
        ON VehicleToEngineConfig.EngineConfigID=EngineConfig.EngineConfigID
    INNER JOIN EngineDesignation
        ON EngineConfig.EngineDesignationID=EngineDesignation.EngineDesignationID
    INNER JOIN EngineVIN
        ON EngineConfig.EngineVINID=EngineVIN.EngineVINID
    INNER JOIN EngineBase
        ON EngineConfig.EngineBaseID=EngineBase.EngineBaseID
    INNER JOIN FuelDeliveryConfig
        ON EngineConfig.FuelDeliveryConfigID=FuelDeliveryConfig.FuelDeliveryConfigID
    INNER JOIN FuelDeliveryType
        ON FuelDeliveryConfig.FuelDeliveryTypeID=FuelDeliveryType.FuelDeliveryTypeID
    INNER JOIN FuelDeliverySubType
        ON FuelDeliveryConfig.FuelDeliverySubTypeID=FuelDeliverySubType.FuelDeliverySubTypeID
    INNER JOIN FuelSystemControlType
        ON FuelDeliveryConfig.FuelSystemControlTypeID=FuelSystemControlType.FuelSystemControlTypeID
    INNER JOIN FuelSystemDesign
        ON FuelDeliveryConfig.FuelSystemDesignID=FuelSystemDesign.FuelSystemDesignID
    INNER JOIN Aspiration
        ON EngineConfig.AspirationID=Aspiration.AspirationID
    INNER JOIN CylinderHeadType
        ON EngineConfig.CylinderHeadTypeID=CylinderHeadType.CylinderHeadTypeID
    INNER JOIN FuelType
        ON EngineConfig.FuelTypeID=FuelType.FuelTypeID
    INNER JOIN IgnitionSystemType
        ON EngineConfig.IgnitionSystemTypeID=IgnitionSystemType.IgnitionSystemTypeID
    INNER JOIN Mfr
        ON EngineConfig.EngineMfrID=Mfr.MfrID
    INNER JOIN EngineVersion
        ON EngineConfig.EngineVersionID=EngineVersion.EngineVersionID
    INNER JOIN Valves
        ON EngineConfig.ValvesID=Valves.Valvesid
    INNER JOIN VehicleToBedConfig
        ON Vehicle.VehicleID=VehicleToBedConfig.VehicleID
    INNER JOIN BedConfig
        ON VehicleToBedConfig.BedConfigID=BedConfig.BedConfigID
    INNER JOIN BedLength
        ON BedConfig.BedLengthID=BedLength.BedLengthID
    GROUP BY part_id

【问题讨论】:

问:您是否运行过EXPLAIN 以获取有关执行计划的详细信息?如果其中任何一个是 MyISAM 表,我建议CHECK TABLE x; 如果报告任何问题,那么REPAIR TABLE x;(但请注意:这可能会导致数据丢失。建议对表进行冷备份,以及作为表的mysqldump,在修复之前)并使用ANALYZE TABLE x;收集统计信息。 我一直在这样做,是的。我认为这是一个查询问题,所以我添加了 JOIN by JOIN 以查看问题出在哪里。现在我正在尝试在这个查询上运行 EXPLAIN SELECT,它在统计中是 100 秒(到目前为止)。 听起来 MySQL 可能正在启动以收集有关表和索引的统计信息。 嘿斯宾塞。有没有办法加快速度? 我会确保统计数据是最新的。如果没有,ANALYZE TABLE x;。这个查询有很多表,所以需要考虑很多连接路径。尝试使用更少的表来运行查询。 【参考方案1】:

我最近遇到了同样的问题:MySQL 开始在将很多表连接在一起的查询中阻塞(陷入状态“统计”)。我找到了一个很好的blog post,解释了为什么会发生这种情况以及如何解决它。

基本上至少在 MySQL 5.5 中,配置参数 optimizer_search_depth 的默认值为 62,这将导致查询优化器随着查询中表数量的增加而以指数方式增加时间。在某个点之后,将开始需要几天甚至更长的时间才能完成查询。

但是,如果您在 my.cnf 中将 optimizer_search_depth 设置为 0,MySQL 会自动选择合适的深度,但将其限制为 7这还不算太复杂。

显然这个问题在 MySQL 5.6 中是fixed,但我自己还没有测试过。

【讨论】:

谢谢!我可以说我正在使用 v5.7 并且我遇到了同样的问题,所以我想它还没有解决。 与 MariaDB 10.0.31 (Ubunti 16.04) 相同的问题,optimizer_search_depth = 0 已修复。谢谢! 该问题在最新的 MariaDB (10.3.12) 中也存在。我的多日查询现在在 40 毫秒内运行。太棒了! 我们在运行 v5.6.49 时遇到了同样的问题,但幸运的是,在设置 optimizer_search_depth = 7 后问题就消失了。【参考方案2】:

我在 4 核和 180GB 内存的 Centos 服务器上遇到了同样的问题。就像您解释的那样,一个简单的查询需要永远运行并停留在统计状态。我在它正在查询的表上运行了OPTIMIZE TABLE,5 分钟后问题就解决了。但是,我从来没有发现它是否真的解决了这个问题。

只是一个建议。

【讨论】:

【参考方案3】:

我昨天花了一天时间处理一个同样麻烦的查询...

另一个快速消除查询优化器挂起的选项是在SELECT 之后添加STRAIGHT_JOIN

例如:

SELECT STRAIGHT_JOIN
table1.column_a,
table1.column_b,
table2.column_a,
table2.column_b
FROM table1
JOIN table2 USING(column_a)

这不是一个理想的解决方案,因为它完全绕过了对连接的查询优化,但是如果您像昨天一样在解决遗留应用程序中的关键任务问题时遇到了困难,它可能会有所帮助。我不建议在每个查询上都使用这个,但在某些情况下它是一种有效的解决方案。

【讨论】:

以上是关于SQL 查询卡在统计状态的主要内容,如果未能解决你的问题,请参考以下文章

优化 SQL 子查询进行统计

SQL alwayson 辅助接点查询统计信息“丢失”导致查询失败

TP SQL统计查询语法

通过手动创建统计信息优化sql查询性能案例

PostgreSQL 按状态统计的记录数

sql server 统计信息