我正在建立一个包含大学课程信息的数据库。 每门课程都可以与
相关联我的数据库包含以下表格:
为了从数据库中检索所有课程(以及相应的作者,学科,机构和级别信息),我使用以下查询:
SELECT DISTINCT aut_last, c.cou_id, cou_name, cou_number, cou_year, cou_term, dis_name, ins_name, ins_classification, lev_name
FROM authorcourse ac1
INNER JOIN authorcourse ac2
ON ac1.cou_id = ac2.cou_id
INNER JOIN author a
ON ac2.aut_id=a.aut_id
INNER JOIN course c
ON ac2.cou_id = c.cou_id
INNER JOIN coursediscipline cd1
ON ac2.cou_id = cd1.cou_id
INNER JOIN coursediscipline cd2
ON cd1.cou_id = cd2.cou_id
INNER JOIN discipline d
ON cd2.dis_id = d.dis_id
INNER JOIN courseinstitution ci1
ON ac2.cou_id = ci1.cou_id
INNER JOIN courseinstitution ci2
ON ci1.cou_id = ci2.cou_id
INNER JOIN institution i
ON ci2.ins_id = i.ins_id
INNER JOIN courselevel cl1
ON ac2.cou_id = cl1.cou_id
INNER JOIN courselevel cl2
ON cl1.cou_id = cl2.cou_id
INNER JOIN level l
ON cl2.lev_id = l.lev_id
当数据库中有15个具有“简单”关系的课程时,此查询很有效。 e.g:
cou_name = 'course1', cou_number = 'C1', cou_year = '1999', cou_term = 'summer'
aut_last = 'Doe1'
dis_name = 'discipline1'
ins_name = 'institution1', ins_classification = 'classification1'
lev_name = 'level1'
- >显示0到14行(共计15行,查询占用0.0118秒) EXPLAIN生成下表:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE ac1 index cou_id aut_id 2 NULL 15 Using index; Using temporary
1 SIMPLE ac2 ref PRIMARY,aut_id,cou_id cou_id 2 ccdb.ac1.cou_id 1 Using index
1 SIMPLE a eq_ref PRIMARY PRIMARY 2 ccdb.ac2.aut_id 1
1 SIMPLE c eq_ref PRIMARY PRIMARY 2 ccdb.ac2.cou_id 1 Using where
1 SIMPLE cd1 ref PRIMARY,cou_id PRIMARY 2 ccdb.ac1.cou_id 1 Using index
1 SIMPLE cd2 ref PRIMARY,cou_id,dis_id PRIMARY 2 ccdb.ac2.cou_id 1 Using where; Using index
1 SIMPLE d eq_ref PRIMARY PRIMARY 2 ccdb.cd2.dis_id 1
1 SIMPLE ci1 ref PRIMARY,cou_id PRIMARY 2 ccdb.ac2.cou_id 1 Using where; Using index
1 SIMPLE ci2 ref PRIMARY,cou_id,ins_id PRIMARY 2 ccdb.ac2.cou_id 1 Using where; Using index
1 SIMPLE i eq_ref PRIMARY PRIMARY 2 ccdb.ci2.ins_id 1
1 SIMPLE cl1 ref PRIMARY,cou_id PRIMARY 2 ccdb.cd1.cou_id 1 Using where; Using index
1 SIMPLE cl2 ref PRIMARY,cou_id,lev_id PRIMARY 2 ccdb.cl1.cou_id 1 Using where; Using index
1 SIMPLE l eq_ref PRIMARY PRIMARY 2 ccdb.cl2.lev_id 1
问题:当有15个具有多种关系的课程时,性能会大幅下降。示例课程:
cou_name = 'course1', cou_number = 'C1', cou_year = '1999', cou_term = 'summer'
aut_last = 'Doe1', 'Doe', 'Doe3', 'Doe4'
dis_name = 'discipline1', 'discipline2', 'discipline3', 'discipline4'
ins_name = 'institution1'(ins_classification = 'classification1'), 'institution2'(ins_classification = 'classification2'), 'institution3'(ins_classification = 'classification3'), 'institution4' (ins_classification = 'classification4')
lev_name = 'level1', 'level2', 'level3', 'level4'
- >显示0到29行(总计3,840,查询耗时14.7039秒) EXPLAIN生成下表:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE c ALL PRIMARY NULL NULL NULL 15 Using temporary
1 SIMPLE ac1 ref PRIMARY,aut_id,cou_id cou_id 2 ccdb.c.cou_id 2 Using index
1 SIMPLE a eq_ref PRIMARY PRIMARY 2 ccdb.ac1.aut_id 1
1 SIMPLE ac2 ref cou_id cou_id 2 ccdb.c.cou_id 2 Using index
1 SIMPLE cd1 ref PRIMARY,cou_id cou_id 2 ccdb.ac1.cou_id 2 Using where; Using index
1 SIMPLE cd2 ref PRIMARY,cou_id,dis_id cou_id 2 ccdb.c.cou_id 2 Using index
1 SIMPLE d eq_ref PRIMARY PRIMARY 2 ccdb.cd2.dis_id 1
1 SIMPLE ci1 ref PRIMARY,cou_id cou_id 2 ccdb.ac1.cou_id 2 Using where; Using index
1 SIMPLE ci2 ref PRIMARY,cou_id,ins_id cou_id 2 ccdb.ac2.cou_id 2 Using where; Using index
1 SIMPLE i eq_ref PRIMARY PRIMARY 2 ccdb.ci2.ins_id 1
1 SIMPLE cl1 ref PRIMARY,cou_id cou_id 2 ccdb.c.cou_id 2 Using index
1 SIMPLE cl2 ref PRIMARY,cou_id,lev_id cou_id 2 ccdb.ci2.cou_id 2 Using where; Using index
1 SIMPLE l eq_ref PRIMARY PRIMARY 2 ccdb.cl2.lev_id 1
当我的PHP网站运行时,我收到以下错误“致命错误:超过30秒的最大执行时间......”
问题:如何加快此查询? 我尝试了几种不同的连接组合 (正如您在EXPLAIN结果中看到的那样)我将所有认为可能相关的列编入索引。
非常感谢任何帮助。
答案 0 :(得分:1)
如果您在“课程视图”类型详细信息页面中提取所有这些数据,那么IT部门会对我说。
如果是这样,我会说,一旦在数据库中开设了一门课程,作者,学科,机构和水平的数量会多久发生变化?
如果从设置的时间开始永远不会改变,那么当它设置时,也将它设置在一个完全非规范化的表中,如下所示:
courseView(cou_id,cou_name,cou_number,cou_year,cou_term,数据)
..在'data'中,您只需输入所有数据的序列化数组。丑陋,但它会很快。
然后,当您按课程ID搜索以提取一个时,您只能搜索一行,一个索引并立即提取所有数据。
...
此外,如果您要让人们按作者搜索,那么您仍然可以使用标准化表格执行此操作,并使用简单的查询。
答案 1 :(得分:1)
您的查询中似乎有不必要的联接。我相信你可以通过以下方式获得同样的结果。它可能会提高您的查询性能。
SELECT DISTINCT aut_last, c.cou_id, cou_name, cou_number, cou_year, cou_term, dis_name, ins_name, ins_classification, lev_name
FROM authorcourse ac
INNER JOIN author a
ON ac.aut_id=a.aut_id
INNER JOIN course c
ON ac.cou_id = c.cou_id
INNER JOIN coursediscipline cd
ON ac.cou_id = cd.cou_id
INNER JOIN discipline d
ON cd.dis_id = d.dis_id
INNER JOIN courseinstitution ci
ON ac.cou_id = ci.cou_id
INNER JOIN institution i
ON ci.ins_id = i.ins_id
INNER JOIN courselevel cl
ON ac.cou_id = cl.cou_id
INNER JOIN level l
ON cl.lev_id = l.lev_id
你有相同的表的冗余连接,似乎没有完成任何事情。
答案 2 :(得分:0)
我不相信有足够的信息可以直接解决您的问题。通过查看您的explain语句,看起来您已正确设置了所有索引,但是您获得的行数是关注的。
罪魁祸首很可能是由于在一张非常大的桌子上进行的桌面扫描正在加剧你所获得的行数。根据我遇到这些问题时的经验,我确定了慢速发生的位置并从那里开始工作。一些使用的策略是临时表或子查询(将它们分解为更小,更易于管理的查询。
另外,要解决PHP致命错误问题,您应该能够使用try / catch异常块来优雅地处理它。