2016-10-26 20 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) 
) 

私が説明し、それがテーブルを示して実行します。Query Analysis

+0

最初に索引を作成することはできますが、問合せ計画を表示することができます。それがなければ何も言いにくいです。 –

+0

ここで 'mktg_spa'と他のものはありません – Drew

+0

申し訳ありません@Drew – 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あなたがしようとしていることははっきりしていません。一般的には、「場所」条件でフィルタリングします。例:ユーザ名の場合、 'left join'バージョンまたは' where ... and(SELECT UserName FROM sys_user WHERE UserId = mktg_account.CreatedBy)=を使用すると、 'username ... 'のように' where ... and sys_user.UserName =' chongIt '元のコードを使用する場合は 'chongIt'となります。ユニット番号やユーザーキーが何であっても、どのテーブルから来てどのようにテーブルを頼りにするべきなのか、同様のことをしなければなりません。 (コードを使用すると、1つの条件で複数のテーブルを結合するのが少し難しいかもしれません)。 – 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 
関連する問題