2017-01-11 10 views
0

私は2つのテーブルを持っています。私はちょうどユーザテーブルと日付テーブルを言うことができます。複数の同じテーブル左結合が非常に遅い

ユーザー

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

Iドン私が何をしたかを知っている人は、あなたが答えを提供したと思う人に私を指摘することができます。みんなありがとう。

+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

あまりにも悪いです。 'create index idx_dates2(id_user、jobnumber、datetype、dateassigned);も試してみてください。おそらく、user_id経由の直接アクセスが早く、次にジョブ番号と日時によってフィルタリングされる可能性があります。私はそれを疑うが、まだ試してみる価値がある。 –

+0

厄介なのは、3つのデータ型に対して3つの副選択を使用し、テーブルにまったく参加しない方が速いことです。クエリには数分ではなく数秒かかります。しかし、私はsubselectsが嫌い、本当に結合が速くなるべきだと思っています。 – Marty

0

これは、同じテーブルに参加するための最良の方法です。たとえ30,000レコードを照会しても、2分かかることはありません。これはデータベースへの複数の接続のような他の問題が原因であるに違いありません。あなたはすべてのそれらを避けるために、条件付きの集約を試みることができる

0

UニーズINDEX(JobNumber, Surname, Firstname)に参加します。それはWHEREORDER BYをカバーしなければならず、それによって 'filesort'が回避されます。

Datesの場合はUNIQUE(ID_User, DateType, JobNumber)ですが、正しいですか? B木の底がのために必要なDateAssigned 3行が隣接することになる含まれていますので、これは、検索をより効率的になります、その後

PRIMARY KEY(JobNumber, ID_User, DateType) 

UNIQUEを交換する、のは、そのテーブルからidを取り除くましょうPKの「クラスタリング」

他のクエリ(読み取りまたは変更)がDatesに触れていない限り、そのテーブルには他のインデックスはありません。

これらのテーブルのサイズはどれくらいですか?あなたは、あなたがその両方を完全に読んでいることに気づきます。しかし私の提案は、各行を何度も一度だけ読むことにつながります。

+0

私はDatesテーブルの元の投稿を修正しました。上記を参照してください、それは私がここにそれを投稿させません。 – Marty

関連する問題