Mysql 难以解释是什么使我的查询如此缓慢

Mysql 难以解释是什么使我的查询如此缓慢,mysql,Mysql,我有一个查询,在MySQL 5.6服务器上需要15秒才能得到350个结果,我无法诊断原因,我对数据库优化还是很陌生。U EXPLAIN visual确实显示了一些非唯一的键查找,但每个键只显示一个1行查找 我无法解释的表格解释,我希望其他人也能解释 我已经尝试将结束LIMIT=350切换到100,10,查询运行所需的时间完全相同,大约为15秒 我已经尝试过禁用视图,但是除了使重新创建此查询变得困难之外,它并没有提高性能 也许相关的,在MySQL数据库中的其他EXPLAIN语句中,我看到了一个在它

我有一个查询,在MySQL 5.6服务器上需要15秒才能得到350个结果,我无法诊断原因,我对数据库优化还是很陌生。U

EXPLAIN visual确实显示了一些非唯一的键查找,但每个键只显示一个1行查找

我无法解释的表格解释,我希望其他人也能解释

我已经尝试将结束
LIMIT=350
切换到100,10,查询运行所需的时间完全相同,大约为15秒

我已经尝试过禁用视图,但是除了使重新创建此查询变得困难之外,它并没有提高性能

也许相关的,在MySQL数据库中的其他EXPLAIN语句中,我看到了一个在它旁边用Materialized引用的视图,但它没有出现在这个查询中使用的三个视图的旁边,事实上,我甚至没有看到被引用的视图,而只看到它们引用的表。这是一个因素吗

我上一次尝试是用特定的列替换最后选择的列,该列是一个
listlineitems.*
,因为我已经阅读了可以提高速度的内容,这只是更好的练习,但我感觉这不会显著改善这种情况

以下是问题-

SELECT 
0 AS 'Check',
DATE_FORMAT(`listlineitems`.`dateEntered`,
        '%Y-%m-%d') AS 'Date Entered',
`listlineitems`.`itemId` AS 'parentTableIdx',
`listlineitems`.`parentProjectId` AS 'parentProjectIdx',
`listlineitems`.`idx` AS 'ID',
IF(`listlineitems`.`active` = 1,
    'Active',
    'Inactive') AS 'Active/Inactive',
CONCAT(`listUsers`.`FirstName`,
        ' ',
        `listUsers`.`LastName`) AS 'Employee',
CASE `listlineitems`.`type`
    WHEN 1 THEN 'Time Entry'
    WHEN 2 THEN 'Expense Entry'
END AS 'Type',
`listcustomers`.`name` AS 'Customer',
`listlocations`.`name` AS 'Location',
`listareas`.`name` AS 'Area',
`listassets`.`name` AS 'Asset',
`listprojects`.`name` AS 'Project',
`listprojects`.`number` 'Project #',
`listprojects`.`autoassign` 'autoassign',
`listactivities`.`name` AS 'Activity',
(CASE `listlineitems`.`type`
    WHEN 1 THEN `listlineitems`.`qty`
    WHEN 2 THEN `listlineitems`.`qty`
END) AS 'Quantity',
`listlineitems`.`taxable` AS 'Taxable',
`listlineitems`.`totalAmount` - `listlineitems`.`taxAmount` AS 'Pre-Tax Amount',
`listlineitems`.`taxAmount` AS 'Tax Amount',
`listlineitems`.`totalAmount` AS 'Total Amount',
`listCustomers`.`idx` AS 'parentCustomerIdx',
`listLocations`.`idx` AS 'parentLocationIdx',
`listAreas`.`idx` AS 'parentAreaIdx',
`listAssets`.`idx` AS 'parentAssetIdx',
CONCAT(`listcustomers`.`name`,
        '/',
        `listlocations`.`name`,
        '/',
        `listareas`.`name`,
        '/',
        `listassets`.`name`,
        '/',
        `listprojects`.`name`) AS 'Path',
IF(`listlineitems`.`customerViewable` = 1,
    'Yes',
    'No') AS 'Cust. Viewable',
(CASE
    WHEN `listlineitems`.`type` = 2 THEN `listexpenseentry`.`TotalCostToPSI` - `listexpenseentry`.`TaxCostToPSI`
    ELSE `listlineitems`.`totalAmount` - `listlineitems`.`taxAmount`
END) AS 'preTaxCostPSI',
(CASE
    WHEN `listlineitems`.`type` = 2 THEN `listexpenseentry`.`TaxCostToPSI`
    ELSE `listlineitems`.`taxAmount`
END) AS 'taxCostPSI',
(CASE
    WHEN `listlineitems`.`type` = 2 THEN `listexpenseentry`.`TotalCostToPSI`
    ELSE `listlineitems`.`totalAmount`
END) AS 'totalCostPSI',
view_solinx2.lastAltered AS 'lastalteredSO',
view_polinx2.lastAlteredPO AS 'lastalteredPO',
view_invlinx2.lastAlteredInv AS 'lastalteredInv',
view_solinx2.lastAlteredAfterConfirmation AS 'lastAlteredAfterConfirmation',
view_solinx2.roleIdSO AS 'roleIdSO',
view_polinx2.roleIdPO AS 'roleIdPO',
view_polinx2.userIdPO AS 'userIdPO',
view_polinx2.lastAlteredafterConfirmation AS 'lastAlteredAfterConfirmationPO',
view_invlinx2.roleIdInv AS 'roleIdInv',
view_invlinx2.userIdInv AS 'userIdInv',
view_invlinx2.lastAlteredafterConfirmation AS 'lastAlteredAfterConfirmationInv',
view_solinx2.roleId AS 'roleId',
view_solinx2.userId AS 'userId',
view_solinx2.soId AS 'SOId',
view_solinx2.autoassignSO AS 'autoassignSO',
IF(view_solinx2.notNeeded = 1,
    'Not Needed',
    view_solinx2.number) AS 'SOname',
view_solinx2.dateEntered AS 'SoDate',
view_solinx2.totalSOAmount AS 'SoTotal',
view_invlinx2.invId AS 'InvId',
IF(view_solinx2.notNeeded = 1,
    '------',
    view_invlinx2.`number`) AS 'InvName',
view_invlinx2.dateEntered AS 'InvDate',
view_invlinx2.amount AS 'InvTotal',
view_polinx2.poId AS 'POId',
IF(view_solinx2.notNeeded = 1,
    '------',
    view_polinx2.`number`) AS 'POName',
view_polinx2.dateEntered AS 'PODate',
view_polinx2.amount AS 'POTotal',
(SELECT 
        listsalesorders.number
    FROM
        listsalesorders
    WHERE
        listsalesorders.idx = autoassign) AS 'test',
`listlineitems`.*
FROM
`listlineitems`
    LEFT JOIN
`listUsers` ON `listlineitems`.`individualId` = `listUsers`.`idx`
    LEFT JOIN
`listprojects` ON `listlineitems`.`parentProjectId` = `listprojects`.`idx`
    LEFT JOIN
`listassets` ON `listlineitems`.`parentAssetId` = `listassets`.`idx`
    LEFT JOIN
`listareas` ON `listlineitems`.`parentAreaId` = `listareas`.`idx`
    LEFT JOIN
`listlocations` ON `listlineitems`.`parentLocationId` = `listlocations`.`idx`
    LEFT JOIN
`listcustomers` ON `listlineitems`.`parentCustomerId` = `listcustomers`.`idx`
    LEFT JOIN
`listactivities` ON `listactivities`.`idx` = `listlineitems`.`activityCode`
    LEFT JOIN
`listexpenseentry` ON (`listexpenseentry`.`idx` = `listlineitems`.`itemId`
    AND `listlineitems`.`type` = 2)
    LEFT JOIN
view_solinx2 ON view_solinx2.idx = listlineitems.idx
    LEFT JOIN
view_polinx2 ON view_polinx2.idx = listlineitems.idx
    LEFT JOIN
view_invlinx2 ON view_invlinx2.idx = listlineitems.idx
GROUP BY `listlineitems`.`idx`
ORDER BY `listlineitems`.`dateEntered` DESC
LIMIT 10;

我不知道我还能做些什么来改进这一点,任何建议都非常感谢。

您正在从listlineitems表(100+K记录)中选择所有内容,加入许多表,然后按idx分组,然后抛出大多数结果

你可以:

  • 尝试将唯一索引(dateEntered,idx)添加到listlineitems
  • 如果可以接受,请尝试按输入的日期限制listlineitems(其中输入的日期>日期(NOW(),间隔30天))。必须为输入的日期编制索引
  • 尝试将selectfromlineitems+grouping+limit放入子查询,这样MySQL将只对子查询返回的这10行进行连接
  • 将依赖子查询(listsalesorders)转换为左联接

什么是listlineitems.idx?是PK吗?SHOW CREATE listlineitems会有所帮助。不同的限制不会改变任何东西,因为在这种情况下,您必须先生成完整结果,然后再进行排序以查找最新的行。这意味着在执行此查询时将有大约200万个密钥查找。您真的需要GROUPBY子句吗?否则,dateEntered上的索引可以向后扫描以查找最新的条目,并且可以避免完全连接和排序。造成大部分损害的是悬挂组BY。一开始删除它确实会给我一些不同的结果(实际上只有几行),但有人告诉我MySQL返回的方式可能有一些随机性,所以这没什么大不了的,因为现在我可以在很短的时间内查询1000个结果。ThanksResult集稍有不同,因为当您按idx分组时,服务器会按idx对其进行内部排序,然后按date desc对该结果集进行排序,只会抛出除前10行以外的所有内容。换句话说,“ORDER BY idx GROUP BY dateEntered DESC”类似于“ORDER BY idx,dateEntered DESC”。所以,如果您喜欢像以前一样设置结果集,您应该通过(不要忘记添加多列索引)Awesome更改顺序,这就解释了这一点。只影响了最后几行,其中一天有很多行。继续做下去感觉好多了。谢谢