2016-03-15 82 views
0

使用PostgreSQL,我在查詢中加入約10桌,它們都是許多一對多的關係。數據庫目前仍然非常小(總共數百行,所有表格組合在一起),但查詢速度非常慢(1分鐘以上的處理時間)。SQL表連接許多一對多很慢

由於每一個加入相乘的行數(接合具有5個記錄2代表的每個將產生25行),其結果很快變得龐大與超過30萬行。查詢的格式如下:

select * from student_profile sp 
    join student_profile_skills sps on sp.id = sps.student_profile_id 
    join student_profile_hobby sph on sp.id = sph.student_profile_id 
    --and other 8 similar joins 
    where sp.id = 1; 

表格很簡單(有2個FKs的聯結表)。這裏推薦的做法是什麼?是查詢必須以更優化的方式編寫還是使用單獨的查詢? Thx提前!

附加信息:


CREATE TABLE student_profile 
(
    id      serial NOT NULL, 
    first_name    text NOT NULL, 
    last_name    text NOT NULL, 
    country_id    integer, 
    city_id     integer, 
    faculty_id    integer, 
    university_id   integer, 
    degree_id    integer, 
    degree_year    integer, 
    created_at    timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    updated_at    timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    CONSTRAINT student_profile_pkey    PRIMARY KEY (id), 
    CONSTRAINT student_profile_country_id_fkey FOREIGN KEY (country_id) REFERENCES country (id), 
    CONSTRAINT student_profile_city_id_fkey  FOREIGN KEY (city_id)  REFERENCES city (id), 
    CONSTRAINT student_profile_faculty_id_fkey FOREIGN KEY (faculty_id) REFERENCES faculty (id), 
    CONSTRAINT student_profile_university_id_fkey FOREIGN KEY (university_id) REFERENCES university (id), 
    CONSTRAINT student_profile_degree_id_fkey  FOREIGN KEY (degree_id)  REFERENCES degree (id) 
); 

CREATE TABLE student_profile_skill 
(
    id     serial     NOT NULL, 
    student_profile_id integer     NOT NULL, 
    skill_id   integer     NOT NULL, 
    position   integer     NOT NULL, 
    created_at   timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    updated_at   timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    CONSTRAINT student_profile_skill_pkey     PRIMARY KEY (id), 
    CONSTRAINT student_profile_skill_student_profile_id_fkey FOREIGN KEY (student_profile_id) REFERENCES student_profile (id), 
    CONSTRAINT student_profile_skill_skill_id_fkey   FOREIGN KEY (skill_id)   REFERENCES skill (id), 
    CONSTRAINT student_profile_skill_unique     UNIQUE (student_profile_id, skill_id), 
    CONSTRAINT student_profile_skill_position_unique   UNIQUE (student_profile_id, position) 
); 
+0

你能表現出一定的查詢和/或表的詳細信息? –

+0

你需要給我們的表的DDL – sagi

+0

查詢是形式:SELECT * FROM student_profile SP加入student_profile_skills SPS上sp.id = sps.student_profile_id上​​sp.id = sph.student_profile_id(和其他8種相似的加入student_profile_hobby SPH加入)其中sp.id = 1; – Thibaut

回答

0

在幾乎所有的許多一對多連接,建議的做法是給他們上一個一對多拆分/多對一之一。但是,如果您的學生擁有超過1個技能/愛好,則您在3路加入中有1對多表格,導致瘋狂數量爲重複記錄。的3路

例加入,你有1名學生有2個技能和1個愛好:

Student  Skill  Hobby 
Smith J. Linguistic Fishing 
Smith J. Profiling Fishing 

我建議1 2的選項:

  1. 只有選擇值你需要當你需要他們,(因爲我無法想象,你需要一臺既愛好和技能,例如:對於愛好和技能的獨立意見
  2. 一個臨時表創建一個腳本,你W¯¯把所有技能都融入到1個領域,並將所有愛好融入另一個領域。 (您可能需要使用光標來構建它們,因此請記住,您不需要經常重建它們)。
+0

Thx爲您的迴應!所以這意味着我應該使用單獨的SQL查詢(例如:select * from student_profile_skill where student_profile_id = 1)並將數據組裝到後端代碼(Node.js)中,而不是加入所有這些表? – Thibaut

+0

是的,除非你有一個非常具體的要求有重複記錄(這是不可能的)。如果您將結果放入網站或軟件中,您只需一次使用1個連接以特定形式顯示結果,或者如果您需要單行顯示1名學生的所有技能/興趣,您需要創建另一個表格並使用光標在每個學生的新表格中創建一個條目,並在表格的相應字段中添加您的技能/興趣的文本描述。 – Zero