简体   繁体   English

MySQL查询非常慢

[英]MySQL query is extremely slow

I have a complex SQL query that linked 6 tables and I found out that it takes about 2 minutes (which I think it shouldn't) to display the result. 我有一个链接6个表的复杂SQL查询,发现显示结果大约需要2分钟(我认为不应该)。 The result will return about 5400++ records. 结果将返回约5400 ++记录。 Is there any way to redesign the query so that it will be able to execute a bit faster? 有什么方法可以重新设计查询,使其能够更快地执行? Thank you for help! 谢谢你的帮助!

My current query is: 我当前的查询是:

SELECT *,
(SELECT MasterDescription FROM sys_master_code WHERE MasterId = mktg_account.CategoryId) AS CustomerCategory, 
(CASE WHEN mktg_account.BusinessSourceId = 97 THEN mktg_account.BusinessSourceOthers ELSE (SELECT MasterDescription FROM sys_master_code WHERE MasterId = mktg_account.BusinessSourceId) END) AS BusinessSource, 
(SELECT TreeName FROM sys_tree WHERE TreeId = mktg_account.TreeId) AS PhaseName, 
(SELECT SolicitorName FROM sys_solicitor WHERE sys_solicitor.SolicitorId =(SELECT SolicitorId FROM mktg_spa WHERE mktg_spa.AccountId = mktg_account.AccountId)) AS SolicitorName, 
(SELECT MasterCode FROM sys_master_code WHERE sys_master_code.MasterId = mktg_account.AgentCompany) AS AgentCompanyText, 
(SELECT MasterCode FROM sys_master_code WHERE sys_master_code.MasterId = mktg_account.FinancialTypeId) AS FinanceSource, 
(SELECT UserName FROM sys_user WHERE UserId = mktg_account.CreatedBy) AS CreatedByName 
FROM mktg_account
WHERE TreeId IN (SELECT TreeId FROM sys_user_access_right WHERE UserId = 4)
AND IsApproved = '1' AND IsDeleted <>'1'
ORDER BY AccountNo

CREATE TABLE IF NOT EXISTS mktg_account (
  AccountId int(10) unsigned NOT NULL AUTO_INCREMENT,
  AccountNo varchar(30) NOT NULL DEFAULT '',
  AccountStatus varchar(1) DEFAULT NULL,
  TreeId int(10) unsigned NOT NULL DEFAULT '0',
  SalesDate datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  PurchasePrice double NOT NULL DEFAULT '0',
  SalesPersonId int(10) unsigned DEFAULT NULL,
  FinancialTypeId int(10) unsigned DEFAULT NULL,
  BillingCustomerId int(10) unsigned DEFAULT NULL,
  EventId int(11) NOT NULL DEFAULT '0',
  CategoryId int(11) NOT NULL DEFAULT '0',
  RealEstateAgentId int(11) NOT NULL DEFAULT '0',
  BusinessSourceId int(10) unsigned DEFAULT NULL,
  BusinessSourceOthers varchar(300) DEFAULT NULL,
  SalesPromotionId int(10) unsigned DEFAULT NULL,
  Remarks text,
  AgentName varchar(100) NOT NULL DEFAULT '',
  AgentCompany varchar(100) NOT NULL DEFAULT '',
  AgentContact varchar(100) DEFAULT NULL,
  AgentRemarks text,
  CreatedDateTime datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  CreatedBy int(10) unsigned NOT NULL DEFAULT '0',
  PurgedDateTime datetime DEFAULT NULL,
  PurgedBy int(10) unsigned DEFAULT NULL,
  PurgedIP varchar(20) DEFAULT NULL,
  IsDeleted tinyint(3) unsigned NOT NULL DEFAULT '0',
  IsApproved tinyint(3) unsigned NOT NULL DEFAULT '1',
  IsPurge tinyint(3) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (AccountId)
)

CREATE TABLE IF NOT EXISTS sys_master_code (
  MasterId int(10) unsigned NOT NULL AUTO_INCREMENT,
  MasterType varchar(20) NOT NULL DEFAULT '',
  MasterCode varchar(100) NOT NULL DEFAULT '',
  MasterDescription varchar(500) NOT NULL DEFAULT '',
  CreatedDateTime datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  CreatedBy int(10) unsigned NOT NULL DEFAULT '0',
  CreatedIP varchar(20) NOT NULL DEFAULT '',
  IsDeleted tinyint(3) unsigned NOT NULL DEFAULT '0',
  IsApproved tinyint(3) unsigned NOT NULL DEFAULT '1',
  IsActive varchar(1) NOT NULL DEFAULT 'Y',
  PRIMARY KEY (MasterId)
) 

CREATE TABLE IF NOT EXISTS sys_tree (
  TreeId int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Tree Running Id',
  TreeName varchar(150) NOT NULL DEFAULT '',
  IsDeleted tinyint(3) unsigned DEFAULT NULL COMMENT '1 = deleted',
  PRIMARY KEY (TreeId)
)

CREATE TABLE IF NOT EXISTS sys_solicitor (
  SolicitorId int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Running id number',
  SolicitorCode varchar(50) NOT NULL DEFAULT '',
  SolicitorName varchar(150) NOT NULL DEFAULT '',
  SolicitorType varchar(50) NOT NULL DEFAULT '',
  ContactPerson varchar(50) NOT NULL DEFAULT '',
  PhoneNo varchar(50) NOT NULL DEFAULT '' COMMENT 'phone number',
  Email varchar(40) NOT NULL DEFAULT '' COMMENT 'email address',
  CreatedDateTime datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  CreatedBy int(10) unsigned NOT NULL DEFAULT '0',
  IsDeleted tinyint(3) unsigned DEFAULT NULL COMMENT '1 = deleted',
  IsApproved tinyint(3) unsigned DEFAULT NULL COMMENT '0 = waiting approval',
  PRIMARY KEY (SolicitorId)
)

CREATE TABLE IF NOT EXISTS sys_user (
  UserId int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'User Running Id',
  UserLoginId varchar(25) NOT NULL DEFAULT '' COMMENT 'User Name For Log In',
  UserName varchar(150) NOT NULL DEFAULT '' COMMENT 'User Real Name',
  Password varchar(50) NOT NULL DEFAULT '' COMMENT 'Password For Log in',
  EmailAddress varchar(100) NOT NULL DEFAULT '',
  IsDeleted tinyint(3) unsigned DEFAULT NULL COMMENT '1 = deleted',
  CreatedDateTime datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Date and time this record created',
  CreatedBy int(10) unsigned NOT NULL DEFAULT '0',
  IsApproved tinyint(3) unsigned DEFAULT NULL COMMENT '0 = waiting approval',
  IsActive varchar(1) NOT NULL DEFAULT 'Y',
  PRIMARY KEY (UserId)
)

CREATE TABLE IF NOT EXISTS sys_user_access_right (
  UserId int(10) unsigned NOT NULL AUTO_INCREMENT,
  TreeId int(10) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (UserId,TreeId),
  KEY FK_SysUserAccessRight_SysTree (TreeId)
)

CREATE TABLE IF NOT EXISTS mktg_spa (
  SpaId int(10) unsigned NOT NULL AUTO_INCREMENT,
  AccountId int(10) unsigned NOT NULL DEFAULT '0',
  SPADate datetime DEFAULT NULL,
  AgreementNo varchar(50) DEFAULT NULL,
  AgreementStatus varchar(10) DEFAULT NULL,
  AgreementDate datetime DEFAULT NULL,
  SPAReference varchar(100) DEFAULT NULL,
  SolicitorId int(10) unsigned DEFAULT NULL,
  SolicitorRefNo varchar(50) DEFAULT NULL,
  TitleDetailReason varchar(200) DEFAULT NULL,
  Remark text,
  CreatedDateTime datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  CreatedBy int(10) unsigned NOT NULL DEFAULT '0',
  IsDeleted tinyint(3) unsigned NOT NULL DEFAULT '0',
  IsApproved tinyint(3) unsigned NOT NULL DEFAULT '1',
  PRIMARY KEY (SpaId)
)

I run EXPLAIN and it show the table : Query Analysis 我运行EXPLAIN并显示该表: 查询分析

You should use join instead of subqueries. 您应该使用join而不是子查询。 Written with join , your query would look like join编写的查询看起来像

SELECT mktg_account.*,
  tbCustomerCategory.MasterDescription as CustomerCategory, 
  (CASE WHEN mktg_account.BusinessSourceId = 97 
   THEN mktg_account.BusinessSourceOthers 
   ELSE tbBusinessSource.MasterDescription 
   END) AS BusinessSource, 
  sys_tree.TreeName as PhaseName, 
  sys_solicitor.SolicitorName,
  tbAgentCompanyText.MasterCode as AgentCompanyText,
  tbFinanceSource.MasterCode as FinanceSource,
  sys_user.UserName as CreatedByName 
from mktg_account
left join sys_master_code as tbCustomerCategory on tbCustomerCategory.MasterId = mktg_account.CategoryId
left join sys_master_code as tbBusinessSource on tbBusinessSource.MasterId = mktg_account.BusinessSourceId
left join sys_tree on sys_tree.TreeId = mktg_account.TreeId
left join mktg_spa on mktg_spa.AccountId = mktg_account.AccountId
left join sys_solicitor on sys_solicitor.SolicitorId = mktg_spa.SolicitorId
left join sys_master_code as tbAgentCompanyText on tbAgentCompanyText.MasterId = mktg_account.AgentCompany
left join sys_master_code as tbFinanceSource on tbFinanceSource.MasterId = mktg_account.FinancialTypeId
left join sys_user on sys_user.UserId = mktg_account.CreatedBy
join sys_user_access_right on sys_user_access_right.TreeId = mktg_account.TreeId 
WHERE sys_user_access_right.UserId = 4
AND mktg_account.IsApproved = '1' AND mktg_account.IsDeleted <> '1'
ORDER BY mktg_account.AccountNo;

And you are missing an index on mktg_spa , so add it: 而且您缺少mktg_spa上的索引,因此添加它:

create index idx_mktg_spa_AccountId on mktg_spa (AccountId);

(You might want to try this first, it might already improve your query enough without converting it to join ). (您可能想先尝试一下,它可能已经改善了您的查询,而没有将其转换为join )。

There might be some potential for an index on mktg_account , but it really depends on your data. mktg_accountmktg_account索引可能会有些潜力,但这实际上取决于您的数据。 If most of your rows are "deleted" or "not approved", you can try eg 如果您的大多数行被“删除”或“未批准”,则可以尝试例如

create index idx_mktg_account_IsApprovedAccountNoIsDeleted 
on mktg_account (IsApproved, AccountNo, IsDeleted);

But if your query returns more than just a small percentage of your rows, this index might actually slow down your query, so test without it first. 但是,如果您的查询返回的行数不只是一小部分,则此索引实际上可能会减慢查询的速度,因此请先进行测试,然后再不使用它。

I'm not going to rewrite the whole thing for you, but here's a start. 我不会为您重写整个过程,但这是一个开始。 Appropriately indexed, this solution will be orders of magnitude faster than what you currently have... 适当地建立索引,此解决方案将比您目前拥有的解决方案快几个数量级...

SELECT a.*
     , c.MasterDescription CustomerCategory
  FROM mktg_account a
  JOIN sys_master_code c
    ON c.MasterId = a.CategoryId
  JOIN sys_user_access_right r
    ON r.TreeId = a.TreeId 
 WHERE r.UserId = 4
   AND a.IsApproved = 1 
   AND IsDeleted <> 1
 ORDER 
    BY a.AccountNo

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM