2017-01-11 29 views
0

我有兩個表,讓我們只說一個用戶表和一個日期表。他們會是這個樣子:多個相同的表左左加入很慢

用戶

ID_User | Title | Firstname | Surname | JobNumber 
1  | Mr | Bob  | Smith | JOB001 
2  | Mrs | Bobbi  | Smythe | JOB001 
... 
13000 

日期

ID_Date | ID_User | DateType | DateAssigned | JobNumber 
1  | 1  | Intent | 21-Jun-2016 | JOB001 
2  | 1  | Reg  | 21-Apr-2017 | JOB001 
3  | 1  | Flight | 21-May-2017 | JOB001 
4  | 2  | Intent | 09-Dec-2016 | JOB001 
5  | 2  | Flight | 01-Jan-2017 | JOB001 
... 
5000 

唯一索引是ID_User + DateType + jobnumber可以。

可能有任何數量的DateTypes。

當我做了如下的查詢時,它需要時間。

select 
    ID_User, 
    Title, 
    Firstname, 
    Surname, 
    JobNumber, 
    DI.DateAssigned as Date_Intent, 
    DR.DateAssigned as Date_Reg, 
    DF.DateAssigned as Date_Flight 
from 
    User as U 
    left join Dates as DI on U.ID_User = DI.ID_User 
    and DI.JobNumber = "JOB001" 
    and DI.DateType = "Intent" 
    left join Dates as DR on U.ID_User = DR.ID_User 
    and DR.JobNumber = "JOB001" 
    and DR.DateType = "Reg" 
    left join Dates as DF on U.ID_User = DF.ID_User 
    and DF.JobNumber = "JOB001" 
    and DF.DateType = "Flight" 
where 
    U.JobNumber = "JOB001" 
order by 
    U.Surname, 
    U.Firstname; 

每個JobNumber將只有300人,最多說5種不同的日期類型。

爲什麼需要這麼長時間?我們正在談2分鐘。

有沒有寫這個的另一種方法?

日期表:

CREATE TABLE `ATL_V2_Assigned_Dates` (
    `ID_Date` bigint(7) unsigned NOT NULL AUTO_INCREMENT, 
    `JobNumber` varchar(10) NOT NULL DEFAULT '', 
    `ID_User` bigint(7) unsigned NOT NULL DEFAULT '0', 
    `DateAssigned` datetime NOT NULL, 
    `DateType` varchar(100) NOT NULL, 
    `Comment` text NOT NULL, 
    `Updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    `Inserted` datetime NOT NULL, 
    PRIMARY KEY (`ID_Date`), 
    UNIQUE KEY `ID_Date` (`ID_Date`) USING BTREE, 
    UNIQUE KEY `unq_idx` (`JobNumber`,`ID_User`,`DateType`) USING BTREE, 
    KEY `JobNumber` (`JobNumber`) USING BTREE, 
    KEY `ID_User` (`ID_User`) USING BTREE, 
    KEY `DateType` (`DateType`) USING BTREE 
) ENGINE=MyISAM AUTO_INCREMENT=3975 DEFAULT CHARSET=utf8; 

UPDATE 2017年1月12日

很奇怪,查詢在0.06S運行現在,這裏是從輸出:

explain select 
    U.ID_User, 
    U.Title, 
    U.Firstname, 
    U.Surname, 
    U.JobNumber, 
    DI.DateAssigned as Date_Intent, 
    DR.DateAssigned as Date_Reg, 
    DF.DateAssigned as Date_Flight 
from 
    ATL_Users as U 
    left join ATL_V2_Assigned_Dates as DI on U.ID_User = DI.ID_User 
    and DI.JobNumber = "ACI001" 
    and DI.DateType = "Deadline - Intention" 
    left join ATL_V2_Assigned_Dates as DR on U.ID_User = DR.ID_User 
    and DR.JobNumber = "ACI001" 
    and DR.DateType = "Event - Registration" 
    left join ATL_V2_Assigned_Dates as DF on U.ID_User = DF.ID_User 
    and DF.JobNumber = "ACI001" 
    and DF.DateType = "Deadline - Flight" 
where 
    U.JobNumber = "ACI001" 
order by 
    U.Surname, 
    U.Firstname; 

+----+-------------+-------+--------+------------------------------------+-----------+---------+------------------------------------+------+----------------------------------------------------+ 
| id | select_type | table | type | possible_keys      | key  | key_len | ref        | rows | Extra            | 
+----+-------------+-------+--------+------------------------------------+-----------+---------+------------------------------------+------+----------------------------------------------------+ 
| 1 | SIMPLE  | U  | ref | JobNumber       | JobNumber | 32  | const        | 506 | Using index condition; Using where; Using filesort | 
| 1 | SIMPLE  | DI | eq_ref | unq_idx,JobNumber,ID_User,DateType | unq_idx | 342  | const,cclliveo_atl.U.ID_User,const | 1 | Using where          | 
| 1 | SIMPLE  | DR | eq_ref | unq_idx,JobNumber,ID_User,DateType | unq_idx | 342  | const,cclliveo_atl.U.ID_User,const | 1 | Using where          | 
| 1 | SIMPLE  | DF | eq_ref | unq_idx,JobNumber,ID_User,DateType | unq_idx | 342  | const,cclliveo_atl.U.ID_User,const | 1 | Using where          | 
+----+-------------+-------+--------+------------------------------------+-----------+---------+------------------------------------+------+----------------------------------------------------+ 

我不不知道我/我們做了什麼,可以讓某人指出我認爲誰提供了答案,我會選中它。多謝你們。

+0

請爲這兩個表提供'SHOW CREATE TABLE',有幾件事我想檢查。還提供'EXPLAIN SELECT ...'。 –

回答

0

你可以嘗試有條件的聚集,以避免所有這些連接 鑑於

drop table if exists Userjobs; 
create table userjobs (ID_User int, Title varchar(10), Firstname varchar(10), Surname varchar(10), JobNumber varchar(10)); 
insert into userjobs values 
(1  , 'Mr' , 'Bob' ,  'Smith' , 'JOB001'), 
(2  , 'Mrs' , 'Bobbi',  'Smythe' , 'JOB001'); 


drop table if exists jobDates; 
create table jobdates(ID_Date int, ID_User int, DateType varchar(10), DateAssigned date, JobNumber varchar(10)); 
insert into jobdates values 
(1  , 1  , 'Intent' , '2016-06-21' , 'JOB001'), 
(2  , 1  , 'Reg'  , '2017-04-21' , 'JOB001'), 
(3  , 1  , 'Flight' , '2017-05-21' , 'JOB001'), 
(4  , 2  , 'Intent' , '2016-12-09' , 'JOB001'), 
(5  , 2  , 'Flight' , '2017-01-01' , 'JOB001'); 

MariaDB [sandbox]> select 
    -> u.ID_User, 
    -> Title, 
    -> Firstname, 
    -> Surname, 
    -> u.JobNumber, 
    -> max(case when datetype = 'intent' then dateassigned else null end) as intent, 
    -> max(case when datetype = 'reg' then dateassigned else null end) reg, 
    -> max(case when datetype = 'flight' then dateassigned else null end) as flight 
    -> from 
    -> Userjobs as U 
    -> left join jobDates as jd on U.ID_User = jd.ID_User 
    ->  and jd.JobNumber = u.jobnumber 
    -> where u.jobnumber = 'JOB001' 
    -> group by u.ID_User, 
    -> Title, 
    -> Firstname, 
    -> Surname, 
    -> u.JobNumber; 
+---------+-------+-----------+---------+-----------+------------+------------+------------+ 
| ID_User | Title | Firstname | Surname | JobNumber | intent  | reg  | flight  | 
+---------+-------+-----------+---------+-----------+------------+------------+------------+ 
|  1 | Mr | Bob  | Smith | JOB001 | 2016-06-21 | 2017-04-21 | 2017-05-21 | 
|  2 | Mrs | Bobbi  | Smythe | JOB001 | 2016-12-09 | NULL  | 2017-01-01 | 
+---------+-------+-----------+---------+-----------+------------+------------+------------+ 
2 rows in set (0.00 sec) 
+0

這看起來是一個很好的做法,我會試試看。 – Marty

0

您可能缺乏適當的索引。請嘗試:

create index idx_user (jobnumber, id_user); 
create index idx_dates (jobnumber, datetype, id_user, dateassigned); 
+0

我有這些索引。 – Marty

+0

太糟糕了。你可以嘗試'創建索引idx_dates2(id_user,jobnumber,datetype,dateassigned);'。也許通過user_id直接訪問比通過jobnumber和datetime首先進行篩選更快。我懷疑它,但它仍然值得一試。 –

+0

令人煩惱的是,3種日期類型使用3種子查詢的速度更快,而且根本不加入表格。查詢需要幾秒鐘而不是幾分鐘。但是,我討厭子選詞,並且認爲連接速度應該更快。 – Marty

0

這是加入同一張表的最佳方式,不確定所花費的時間。即使你通過30,000條記錄查詢,也不需要2分鐘。這必須是由於其他一些問題,比如與數據庫的多重連接。

0

U需要INDEX(JobNumber, Surname, Firstname)。這應該包括WHEREORDER BY,從而避免'文件'。

對於Dates,您有UNIQUE(ID_User, DateType, JobNumber),對嗎?讓我們從該表中擺脫id,然後更換UNIQUE

PRIMARY KEY(JobNumber, ID_User, DateType) 

這將使得查找更爲有效,因爲B樹的底部將包含將相鄰所需的DateAssigned三排,因爲PK的「聚集」。

除非您有其他一些觸摸Dates的查詢(讀取或修改),否則該表上應該沒有其他索引。

這些表格有多大?你意識到你會完全閱讀他們兩個。不過,我的建議會導致每行只讀一次,而不是多次。

+0

我已將原始帖子修改爲日期表中的內容。請參閱上文,它不會讓我在這裏發佈。 – Marty