2016-10-26 2 views
0

6 개의 테이블을 연결하는 복잡한 SQL 쿼리가 있는데 결과를 표시하는 데 약 2 분이 걸리는 것으로 나타났습니다. 결과는 약 5400 ++ 레코드를 반환합니다. 조금 더 빨리 실행할 수 있도록 쿼리를 다시 디자인 할 수있는 방법이 있습니까? 도와 줘서 고마워!MySQL 쿼리가 매우 느림

나의 현재 쿼리는 다음과 같습니다

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) 
) 

나는 EXPLAIN 실행하고 테이블을 보여 Query Analysis

+0

먼저 인덱스를 만들지 만 쿼리 계획을 표시 할 수 있습니다. 그것 없이는 아무 말도하기가 어렵습니다. –

+0

여기서'mktg_spa'와 그 밖의 것이 없습니다 – Drew

+0

죄송합니다. @Drew의 질문에 mktg_spa를 이미 추가했습니다. – chonglt

답변

1

대신 하위 쿼리 join를 사용해야합니다. 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; 

과 같을 것이다 그리고 당신은 mktg_spa에 인덱스를 누락, 그래서 추가 :

create index idx_mktg_spa_AccountId on mktg_spa (AccountId); 

(당신은 이미 향상시킬 수 있습니다, 먼저이 시도 할 수 있습니다 당신의 쿼리를 join으로 변환하지 않고 충분히 쿼리).

mktg_account에 대한 색인의 잠재력은있을 수 있지만 데이터에 따라 달라질 수 있습니다. 대부분의 행이 '삭제됨'또는 '승인되지 않음'인 경우 예를 들어

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

그러나 쿼리가 행의 단지 작은 비율 이상을 반환하는 경우,이 지수는 실제로 쿼리를 느리게하므로 검사 먼저 않고 있습니다.

+0

대단히 감사합니다 !!!!!!!! mktg_spa에 인덱스를 추가하면 쿼리가 훨씬 빠르게 실행됩니다! 하위 쿼리와 조인을 사용하면 레코드를 검색하는 데 동일한 시간이 걸린다는 것을 알았습니다! 도움을 주셔서 감사합니다. – chonglt

+0

안녕하세요. 나는 당신에게 묻고 싶은 질문을 원해. 사용자 키를 기반으로 유닛 번호를 필터링하려면 어떻게해야합니까? 어디에서 조건을 추가해야합니까? – chonglt

+0

@ chonglt 무엇을하려고하는지 명확하지 않습니다. 일반적으로 "where"조건을 필터링합니다. 예 : 사용자 이름에 대해,'left join '버전이나'where ... 그리고 (SELECT UserName FROM sys_user WHERE UserId = mktg_account.CreatedBy) ='를 사용하면'where ... and sys_user.UserName = 'chongIt' 원래 코드를 사용한다면 'chongIt'입니다. 당신의 유닛 번호 나 사용자 키가 무엇이든, 그들이 가져온 테이블과 그들이 서로 어떻게 의존해야하는지, 당신은 비슷한 것을해야합니다. (코드를 사용하는 경우 하나의 조건에서 여러 테이블을 결합하는 것이 다소 까다로울 수 있습니다.) – Solarflare

0

나는 당신을 위해 모든 것을 다시 쓰지 않을 것이지만 여기에 시작이 있습니다. 적절하게 인덱싱 된이 솔루션은 현재 가지고있는 것보다 훨씬 빠른 속도를 보입니다. ...

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 
관련 문제