【问题标题】:Optimizing mysql query for better performance to get low execution time优化 mysql 查询以获得更好的性能以缩短执行时间
【发布时间】:2021-03-29 09:37:56
【问题描述】:

目前我的 php 代码中有这个 mysql 查询。我想更好地优化它,因为这个查询当前在一个 while 循环中,并且这个查询单独需要 25 秒。因此,循环越大,一遍又一遍地执行此查询所需的时间在很短的时间内就开始变得疯狂。所以我很想在这方面得到一些帮助。

$select_count = "select site_id, "
                . "(select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '$from' AND '$to') AND "
                . "Site_ID = $site_id and IS_Nozzle = 1) IS_Nozzle, "
                . "(select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '$from' AND '$to') AND "
                . "Site_ID = $site_id and IS_Electronic_Components = 1) IS_Electronic_Components, "
                . "(select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '$from' AND '$to') AND "
                . "Site_ID = $site_id and IS_Power_device = 1) IS_Power_device, "
                . "(select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '$from' AND '$to') AND "
                . "Site_ID = $site_id and IS_Consumable = 1) IS_Consumable, "
                . "(select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '$from' AND '$to') AND "
                . "Site_ID = $site_id and IS_Hose = 1) IS_Hose, "
                . "(select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '$from' AND '$to') AND "
                . "Site_ID = $site_id and IS_Switch = 1) IS_Switch, "
                . "(select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '$from' AND '$to') AND "
                . "Site_ID = $site_id and IS_Valve = 1) IS_Valve, "
                . "(select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '$from' AND '$to') AND "
                . "Site_ID = $site_id and IS_Housing_Frame = 1) IS_Housing_Frame, "
                . "(select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '$from' AND '$to') AND "
                . "Site_ID = $site_id and IS_Pump = 1) IS_Pump, "
                . "(select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '$from' AND '$to') AND "
                . "Site_ID = $site_id and IS_Totalizer = 1) IS_Totalizer, "
                . "(select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '$from' AND '$to') AND "
                . "Site_ID = $site_id and IS_Flow_Meter = 1) IS_Flow_Meter, "
                . "(select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '$from' AND '$to') AND "
                . "Site_ID = $site_id and IS_Swivel = 1) IS_Swivel, "
                . "(select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '$from' AND '$to') AND "
                . "Site_ID = $site_id and IS_Submersible = 1) IS_Submersible, "
                . "(select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '$from' AND '$to') AND "
                . "Site_ID = $site_id and IS_Other = 1) IS_Other "
                . "FROM Site_detail x "
                . "WHERE is_maintenance = 1";

编辑

这是 sql 查询

select site_id
     , (select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '2020-12-1' AND '2020-12-2') AND Site_ID = 1342 and IS_Nozzle = 1) IS_Nozzle
     , (select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '2020-12-1' AND '2020-12-2') AND Site_ID = 1342 and IS_Electronic_Components = 1) IS_Electronic_Components
     , (select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '2020-12-1' AND '2020-12-2') AND Site_ID = 1342 and IS_Power_device = 1) IS_Power_device
     , (select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '2020-12-1' AND '2020-12-2') AND Site_ID = 1342 and IS_Consumable = 1) IS_Consumable
     , (select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '2020-12-1' AND '2020-12-2') AND Site_ID = 1342 and IS_Hose = 1) IS_Hose
     , (select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '2020-12-1' AND '2020-12-2') AND Site_ID = 1342 and IS_Switch = 1) IS_Switch
     , (select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '2020-12-1' AND '2020-12-2') AND Site_ID = 1342 and IS_Valve = 1) IS_Valve
     , (select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '2020-12-1' AND '2020-12-2') AND Site_ID = 1342 and IS_Housing_Frame = 1) IS_Housing_Frame
     , (select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '2020-12-1' AND '2020-12-2') AND Site_ID = 1342 and IS_Pump = 1) IS_Pump
     , (select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '2020-12-1' AND '2020-12-2') AND Site_ID = 1342 and IS_Totalizer = 1) IS_Totalizer
     , (select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '2020-12-1' AND '2020-12-2') AND Site_ID = 1342 and IS_Flow_Meter = 1) IS_Flow_Meter
     , (select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '2020-12-1' AND '2020-12-2') AND Site_ID = 1342 and IS_Swivel = 1) IS_Swivel
     , (select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '2020-12-1' AND '2020-12-2') AND Site_ID = 1342 and IS_Submersible = 1) IS_Submersible
     , (select count(id) from Tbl_WO_Detail WHERE Description != 'PM' AND (WO_Date between '2020-12-1' AND '2020-12-2') AND Site_ID = 1342 and IS_Other = 1) IS_Other 
  FROM Site_detail x 
 WHERE is_maintenance = 1

并且 对于表 site_details

CREATE TABLE `site_detail` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `site_id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
 `site_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
 `owner_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
 `owner_phone` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
 `commission_date` date DEFAULT NULL,
 `noofpressure_unit` bigint(20) DEFAULT NULL,
 `noofsuction_unit` bigint(20) DEFAULT NULL,
 `region_id` bigint(20) DEFAULT NULL,
 `oilcompany_id` bigint(20) DEFAULT NULL,
 `subregion_id` bigint(20) DEFAULT NULL,
 `natures` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
 `is_maintenance` tinyint(4) DEFAULT NULL,
 `site_no` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
 `Asset_Qty` bigint(20) unsigned DEFAULT NULL,
 `TimeStamp` datetime DEFAULT NULL,
 PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=46712 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=DYNAMIC

CREATE TABLE `tbl_wo_detail` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `WO_No` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
 `Caller_No` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
 `Contact_Person` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
 `WO_Date` date DEFAULT NULL,
 `WO_Time` time DEFAULT NULL,
 `OC_Date` date DEFAULT NULL,
 `OC_Time` time DEFAULT NULL,
 `OC_ID` int(11) DEFAULT NULL,
 `Complain_No` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
 `Description` varchar(1000) COLLATE utf8_unicode_ci DEFAULT NULL,
 `Site_ID` int(11) DEFAULT NULL,
 `Subregion` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
 `Target_Date` date DEFAULT NULL,
 `Target_Time` time DEFAULT NULL,
 `WO_Priority` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
 `WO_Status` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
 `Down_Time` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
 `Remarks` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
 `Task_Mode` varchar(50) COLLATE utf8_unicode_ci DEFAULT 'Open',
 `Detail_Other` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
 `Solution` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
 `Finish_Date` date DEFAULT NULL,
 `Finish_T1` time DEFAULT NULL,
 `Finish_T2` time DEFAULT NULL,
 `Pay_Mode` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
 `PO_Number` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
 `Customer_Name` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
 `Customer_Comments` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
 `Prd_Qty` int(11) DEFAULT NULL,
 `Tech_Qty` int(11) DEFAULT NULL,
 `MRRNo` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
 `IS_Nozzle` tinyint(4) DEFAULT 0,
 `IS_Electronic_Components` tinyint(4) DEFAULT 0,
 `IS_Power_device` tinyint(4) DEFAULT 0,
 `IS_Consumable` tinyint(4) DEFAULT 0,
 `IS_Hose` tinyint(4) DEFAULT 0,
 `IS_Switch` tinyint(4) DEFAULT 0,
 `IS_Valve` tinyint(4) DEFAULT 0,
 `IS_Housing_Frame` tinyint(4) DEFAULT 0,
 `IS_Pump` tinyint(4) DEFAULT 0,
 `IS_Totalizer` tinyint(4) DEFAULT 0,
 `IS_Flow_Meter` tinyint(4) DEFAULT 0,
 `IS_Swivel` tinyint(4) DEFAULT 0,
 `IS_Preventive_Maintenance` tinyint(4) DEFAULT 0,
 `IS_Submersible` tinyint(4) DEFAULT 0,
 `IS_Other` tinyint(4) DEFAULT 0,
 `Edit_DateTime` datetime DEFAULT NULL,
 `chkVIS` tinyint(4) DEFAULT 0,
 PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=444908 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=DYNAMIC

【问题讨论】:

  • 如果您需要优化,请提供最终的 SQL 代码,而不是构建它的 PHP 表达式。为所有表添加定义 (CREATE TABLE) 并为当前查询添加 EXPLAIN。
  • 当然我也会添加。
  • 你提到了 PHP。看到您可以访问应用程序级代码,这整个方法对我来说似乎是错误的

标签: php mysql database pivot-table


【解决方案1】:

看起来

SELECT site_id, 
       SUM(IS_Nozzle = 1) IS_Nozzle, 
       SUM(IS_Electronic_Components = 1) IS_Electronic_Components, 
       SUM(IS_Power_device = 1) IS_Power_device, 
       SUM(IS_Consumable = 1) IS_Consumable, 
       SUM(IS_Hose = 1) IS_Hose, 
       SUM(IS_Switch = 1) IS_Switch, 
       SUM(IS_Valve = 1) IS_Valve, 
       SUM(IS_Housing_Frame = 1) IS_Housing_Frame, 
       SUM(IS_Pump = 1) IS_Pump, 
       SUM(IS_Totalizer = 1) IS_Totalizer, 
       SUM(IS_Flow_Meter = 1) IS_Flow_Meter, 
       SUM(IS_Swivel = 1) IS_Swivel, 
       SUM(IS_Submersible = 1) IS_Submersible, 
       SUM(IS_Other = 1) IS_Other 
FROM Site_detail x 
JOIN Tbl_WO_Detail y USING (site_id)
WHERE x.is_maintenance = 1
  AND y.Description != 'PM' 
  AND y.WO_Date between '$from' AND '$to'
GROUP BY site_id;

如果条件中使用的列(IS_Nozzle、IS_Electronic_Components 等)是布尔列(仅包含 0 或 1),则可以删除 = 1

附言。在最后一种情况下,我建议使用一列 SET 数据类型而不是许多单独的列。

【讨论】:

  • 我会看看这个查询然后回复你
【解决方案2】:

我会推荐一种 Akina 方法的变体:

SELECT sd.site_id, wd.IS_Nozzle, wd.IS_Electronic_Components,  wd.IS_Power_device,  wd.IS_Consumable, 
       wd.IS_Hose wd.IS_Switch, wd.IS_Valve, wd.IS_Housing_Frame, wd.IS_Pump, wd.IS_Totalizer, 
       wd.IS_Flow_Meter, wd.IS_Swivel, wd.IS_Submersible, wd.IS_Other 
FROM Site_detail sd JOIN
     (SELECT SUM(IS_Nozzle = 1) as IS_Nozzle, 
             SUM(IS_Electronic_Components = 1) as IS_Electronic_Components, 
             SUM(IS_Power_device = 1) as IS_Power_device, 
             SUM(IS_Consumable = 1) as IS_Consumable, 
             SUM(IS_Hose = 1) as IS_Hose, 
             SUM(IS_Switch = 1) as IS_Switch, 
             SUM(IS_Valve = 1) as IS_Valve, 
             SUM(IS_Housing_Frame = 1) as IS_Housing_Frame, 
             SUM(IS_Pump = 1) as IS_Pump, 
             SUM(IS_Totalizer = 1) as IS_Totalizer, 
             SUM(IS_Flow_Meter = 1) as IS_Flow_Meter, 
             SUM(IS_Swivel = 1) as IS_Swivel, 
             SUM(IS_Submersible = 1) as IS_Submersible, 
             SUM(IS_Other = 1) as IS_Other
      FROM Tbl_WO_Detail wd
      WHERE wd.Description <> 'PM' AND
            wd.WO_Date BETWEEN ? AND ?
      GROUP BY wd.site_id
     ) wd
      USING (site_id)
WHERE sd.is_maintenance = 1
GROUP BY sd.site_id;

这可以使用Site_detail(id_maintenance, site_id)Tbl_WO_Detail(WO_Date, Description) 上的索引。

注意在此查询中使用有意义的 表别名,而不是任意字母,例如xy

最重要的是:将参数值作为参数传递。 不要用参数值混淆查询字符串!

【讨论】:

    【解决方案3】:

    要解决的四件事;很难说哪个对性能的帮助最大:

    Pivot:关于如何有效地进行旋转有两个很好的答案。更多...

    site_id: 一个主要问题:site_id 在两个细节中具有不同的数据类型(VARCHAR 与 INT)。这导致JOIN 的性能很差。修理它!当你在做的时候,考虑一下site_id是否应该是site_detailPRIMARY KEY

    引擎:使用 InnoDB,而不是 MyISAM。

    索引:

    site_detail:  (is_maintenance, site_id)
    wo_detail:    (date, site_id)
    wo_detail:    (site_id, date)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-01-08
      • 1970-01-01
      • 2018-09-18
      • 1970-01-01
      • 1970-01-01
      • 2021-05-10
      • 1970-01-01
      相关资源
      最近更新 更多