如何使用MYSQL JOIN结构?以及如何优化查询时间

How to use MYSQL JOIN structure? and how to optimize query time

我有一些无法解决的 MYSQL 数据库问题。

  1. 我下面的查询花费了太多时间,导致系统挂起。我正在尝试使用“JOIN”构造来开发它。但这次我尝试使用“SUM”进行聚合,将查询减少到一行。用“JOIN”做这个工作可以吗?或者我应该如何改进这个查询。

  2. 此数据库在 ASP .NET 应用程序中与总共 22 个客户端设备一起使用。正如我上面提到的,在查询时间较长的情况下,当客户端设备同时向数据库发送查询时,客户端设备会冻结。我不明白的是为什么浏览器应用程序中的查询会让所有设备等待。 MYSQL 中的每个查询不是作为单独的“线程”处理的吗?因此,如果查询的 return 时间为 10 秒,所有客户端是否会等待 10 秒以便在浏览器中回答查询?

SELECT *,
(SELECT MachModel FROM machine WHERE MachCode=workorder.MachCode) AS MachModel,  
(SELECT RawMaterialDescription FROM rawmaterials WHERE RawMaterialCode=workorder.ProductRawMaterial) AS RawMaterialDescr, 
(SELECT RawMaterialColor FROM rawmaterials WHERE RawMaterialCode=workorder.ProductRawMaterial) AS RawMaterialColor,
(SELECT StaffName FROM staff WHERE AccountName=workorder.AssignStaff) AS AssignStaffName, 
(SELECT StaffCode FROM staff WHERE AccountName=workorder.AssignStaff) AS AssignStaffCode,
(SELECT MachStatus FROM machine WHERE MachCode=workorder.MachCode) AS MachStatus,
(SELECT SUM(xStopTime) FROM workorderb WHERE xWoNumber=workorder.WoNumber) AS WoTotalStopTime 
FROM workorder 
WHERE WoStatus=3 
ORDER BY PlanProdStartDate DESC, WoSortNumber, WoNumber LIMIT 100
SELECT workorder.*,machine.MachModel,machine.MachStatus,rawmaterials.RawMaterialDescription,rawmaterials.RawMaterialColor,staff.StaffName,staff.StaffCode,SUM(workorderb.xStopTime) 
FROM workorder  
LEFT JOIN machine ON machine.MachCode=workorder.MachCode  
LEFT JOIN rawmaterials ON rawmaterials.RawMaterialCode=workorder.ProductRawMaterial 
LEFT JOIN staff ON staff.AccountName=workorder.AssignStaff  
LEFT JOIN workorderb ON workorderb.xWoNumber=workorder.WoNumber 
WHERE workorder.WoStatus=3 
ORDER BY workorder.PlanProdStartDate DESC, workorder.WoSortNumber, workorder.WoNumber LIMIT 100
CREATE TABLE `workorder` (
  `WoNumber` varchar(20) NOT NULL,
  `MachCode` varchar(15) NOT NULL,
  `PlannedMoldCode` varchar(10) NOT NULL,
  `PartyNumber` smallint(6) NOT NULL,
  `PlanProdCycleTime` smallint(6) NOT NULL,
  `CalAverageCycleTime` float(15,1) unsigned NOT NULL,
  `ProductRawMaterial` varchar(30) NOT NULL,
  `PlanProdStartDate` date NOT NULL,
  `PlanProdFinishDate` int(10) unsigned NOT NULL,
  `WoStartDate` datetime DEFAULT NULL,
  `WoFinishDate` datetime DEFAULT NULL,
  `WoWorkTime` int(10) unsigned NOT NULL,
  `WoSystemProductivity` smallint(6) unsigned NOT NULL,
  `AssignStaff` varchar(50) DEFAULT '',
  `WoStatus` smallint(6) NOT NULL,
  `WoSortNumber` int(10) unsigned NOT NULL,
  `CycleCount` int(11) unsigned NOT NULL,
  `ControlDate` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP,
  `WoProductionStatus` smallint(6) NOT NULL DEFAULT '0',
  `Creator` varchar(50) NOT NULL,
  `Changer` varchar(50) NOT NULL,
  `CreateDate` datetime NOT NULL,
  PRIMARY KEY (`WoNumber`) USING BTREE,
  KEY `WoNumber` (`WoNumber`) USING BTREE,
  KEY `WoNumber_2` (`WoNumber`) USING BTREE,
  KEY `WoNumber_3` (`WoNumber`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC
CREATE TABLE `machine` (
  `MachCode` varchar(15) NOT NULL,
  `MachModel` varchar(30) NOT NULL,
  `FirstProdDate` date NOT NULL,
  `MachCapacity` smallint(6) NOT NULL,
  `MachStatus` smallint(6) NOT NULL,
  `NowMoldOnMach` varchar(10) NOT NULL DEFAULT '',
  `NowMachOperator` varchar(50) NOT NULL DEFAULT '',
  `NowWorkOrder` varchar(20) NOT NULL DEFAULT '',
  `IPNumber` varchar(15) NOT NULL,
  `Creator` varchar(50) NOT NULL,
  `Changer` varchar(50) NOT NULL,
  `ControlDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `OperatorLoginDate` datetime DEFAULT NULL,
  `Message` varchar(500) DEFAULT NULL,
  `MessageReaded` smallint(6) DEFAULT '0',
  `StaffName` varchar(50) DEFAULT 'OSIS',
  `StaffImage` varchar(255) DEFAULT '',
  `StopDesc` varchar(30) DEFAULT 'OSIS',
  `StopTime` datetime DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`MachCode`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC
CREATE TABLE `rawmaterials` (
  `RawMaterialCode` varchar(15) NOT NULL,
  `RawMaterialDescription` varchar(30) NOT NULL,
  `RawMaterialColor` varchar(30) NOT NULL,
  PRIMARY KEY (`RawMaterialCode`) USING BTREE,
  KEY `RawMaterialCode` (`RawMaterialCode`) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC
CREATE TABLE `staff` (
  `StaffCode` varchar(15) DEFAULT NULL,
  `StaffCardCode` varchar(10) DEFAULT NULL,
  `StaffName` varchar(50) NOT NULL,
  `StaffPassword` varchar(10) NOT NULL,
  `StaffStatus` smallint(6) NOT NULL DEFAULT '2',
  `StaffDateOfStart` date NOT NULL,
  `StaffBirthDay` date DEFAULT NULL,
  `StaffGender` varchar(5) DEFAULT NULL,
  `StaffRoleA` smallint(6) NOT NULL,
  `StaffEmail` varchar(100) NOT NULL,
  `StaffImageLink` varchar(255) DEFAULT NULL,
  `AccountName` varchar(50) NOT NULL,
  `StaffRoleB` smallint(6) NOT NULL,
  `StaffRoleD` smallint(6) NOT NULL,
  `StaffRoleE` smallint(6) NOT NULL,
  `StaffRoleC` smallint(6) NOT NULL,
  `StaffRoleF` smallint(6) NOT NULL,
  `StaffRoleG` smallint(6) NOT NULL,
  `StaffRoleH` smallint(6) NOT NULL,
  `StaffRoleI` smallint(6) NOT NULL,
  `StaffRoleJ` smallint(6) NOT NULL,
  `StaffRoleK` smallint(6) NOT NULL,
  `StaffRoleL` smallint(6) NOT NULL,
  `StaffRoleM` smallint(6) NOT NULL,
  `StaffRoleN` smallint(6) NOT NULL,
  `StaffConnection` smallint(6) NOT NULL DEFAULT '2',
  `MachineWorked` varchar(15) DEFAULT NULL,
  `WorkOrderWorked` varchar(20) DEFAULT NULL,
  `StaffGroup` varchar(50) NOT NULL,
  `Creator` varchar(50) NOT NULL,
  `Changer` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`AccountName`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC
CREATE TABLE `workorderb` (
  `xWoNumber` varchar(20) NOT NULL,
  `xMachCode` varchar(15) NOT NULL,
  `xPlannedMoldCode` varchar(10) NOT NULL,
  `xPartyNumber` smallint(6) NOT NULL,
  `xStaffName` varchar(50) NOT NULL,
  `xStopCode` smallint(6) NOT NULL,
  `xStopStartTime` datetime NOT NULL,
  `xStopFinishTime` datetime DEFAULT NULL,
  `xStopTime` int(11) DEFAULT NULL,
  PRIMARY KEY (`xMachCode`,`xStopStartTime`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC

您的连接查询就快完成了:它只是缺少一个 GROUP BY 子句。
我在 SELECT 中用 workorder.WoNumber 替换了 workorder.* 并添加了 GROUP BY workorder.WoNumber.
您可以根据需要在 SELECT 中添加任意数量的 workorder 列,但您必须在 GROUP BY.

中列出它们
SELECT workorder.WoNumber,machine.MachModel,machine.MachStatus,rawmaterials.RawMaterialDescription,rawmaterials.RawMaterialColor,staff.StaffName,staff.StaffCode,SUM(workorderb.xStopTime) 
FROM workorder  
LEFT JOIN machine ON machine.MachCode=workorder.MachCode  
LEFT JOIN rawmaterials ON rawmaterials.RawMaterialCode=workorder.ProductRawMaterial 
LEFT JOIN staff ON staff.AccountName=workorder.AssignStaff  
LEFT JOIN workorderb ON workorderb.xWoNumber=workorder.WoNumber 
WHERE workorder.WoStatus=3 
GROUP BY workorder.WoNumber  \* <<= ADD OTHER COLUMNS HERE AS NEEDED *\
ORDER BY workorder.PlanProdStartDate DESC, workorder.WoSortNumber, workorder.WoNumber LIMIT 100;

db<>fiddle here

使用 InnoDB,而不是 MyISAM。INSERTing 时,MyISAM 锁定整个 table; InnoDB 在插入时经常可以让其他线程运行。

其他说明

workorderwonumber 上有 4 个相同的索引;保留PK,折腾剩下的。请注意,PRIMARY KEY 是一个索引。检查其他 table 是否有冗余密钥。

ORDER BY PlanProdStartDate DESC, WoSortNumber, WoNumber需要DESC和ASC的混合吗?如果没有,这里可能会有优化。

正如 Kendle 所建议的那样,JOINs 会更快,因为在某些情况下需要两次相同的 table。如果可能缺少值,那么 LEFT 可能会有用;它不会改变性能。

需要:

workorderb: INDEX(xWoNumber, xStopTime)

xStopTime是经过的时间吗?还是一天中的某个时间?