2009-10-19 106 views
0

我正在设计一个测验和quizz结果项目。所以我有两张桌子:quizz_result和quizz。 quizz在ID上具有主键,quizz_result具有用于quizz标识的外键QUIZZ_ID。两个左连接和一个查询MySQL性能问题

下面的查询旨在按日期按照排序的信息排序进行公开测验:如果当前用户(683735)接受了这个quizz并且有一个有效结果(> 0),并且有多少人填充了这个quizz直到此时间点。

所以我做了两个没有这个简单的查询连接:

select  
    a.*, 
    COUNT(countt.QUIZZ_ID) SUMFILL 
from 
    quizz a 
    left join quizz_result countt 
    on countt.QUIZZ_ID = a.ID 
group by 
    a.ID 

并添加索引这些列: QUIZZ:

ID, (ID, DATE), PUBLIC, (PUBLIC, DATE) 

而且在quizz_result:

ID, (QUIZZ_ID, USER_ID), QUIZZ_ID, USER_ID, (QUIZZ_ID, QUIZZ_RESULT_ID) 

但是,当我查询时,大约需要一分钟。我在QUIZZ_RESULTS中只有34k行,在QUIZZ表中有120行。

当我做EXPLAIN此查询我得到这个:

SELECT TYPE: simple, possible keys: IDX_PUBLIC,DATE, rows: 34 extra: Using where; Using temporary; Using filesort 
SELECT TYPE: simple, possible keys: IDX_QUIZZ_USER,IDX_QUIZZ_RES_RES_QUIZ,IDX_USERID,I..., rows: 1, extra: nothing here 
SELECT TYPE: simple, possible keys: IDX_QUIZZ_USER,IDX_QUIZ_RES_RES_QUIZZ,ID_RESULT_ID, rows: 752, extra: Using index 

而且我不知道该怎么办,以优化此查询什么。我看到这个:

Using where; Using temporary; Using filesort 

但仍然我不知道如何得到这个更好,或者也许最后选择的行数是高? 752?

如何优化此查询?

编辑:我已经向上查询这一只有一个左连接,因为它具有相同的长执行时间。编辑2:我确实删除了所有的东西,并且它:这个简单的选择与一个查询需要1s执行。如何优化它?

+0

尝试运行OPTIMIZE TABLE QUIZZ,quizz_result; – Greg 2009-10-19 21:17:13

+0

@Greg谢谢你的提示。我做到了,但时间还是一样的 – 2009-10-19 21:31:59

回答

0

我把它改成这样:

select  
    a.*, 
    COUNT(a.ID) SUMFILL 
from 
    quizz a 
    left join quizz_result countt 
    on countt.QUIZZ_ID = a.ID 
group by 
    a.ID 

而且它现在是不错的。

0

怎么样(USER_ID,QUIZZ_ID,QUIZZ_RESULT_ID)上的索引,因为它们都是AND'd在一起?

+0

我认为你是对的,应该有所帮助,但我已经将它添加到了这张表中,但不幸的是时间是相同的。所以也许这将是下一个优化。在这个查询中仍然有很大和不好的地方 – 2009-10-19 21:26:07

+0

只剩下一个左连接仍然很慢?我没有很多经验,但这看起来不对。是否有很多其他需要很长时间的查询看起来不应该?你是否将默认值中的任何数据库引擎参数(线程,共享内存等)更改了?我猜在这之前,检查你是否真的在quizz_result上设置了外键限制。 – Kev 2009-10-20 17:01:00

1

尝试从你的连接中取出一些附加条件。 将它们移到where子句有时可以提供帮助。另外,考虑将核心连接放入它们自己的子查询中,然后用where子句限制它。

+0

我尝试但没有成功,你可以更具描述性? – 2009-10-19 22:05:02

+0

由于我原来的答案你的查询已经改变了一些,我不认为我的答案是有效的。看看这两张表上的索引。确保你在加入的所有列上都有索引。只要有可能,就加入每个表内的唯一值(例如主键和外键)。 – 2009-10-20 14:12:23

0

试试这个:

SELECT q.*, 
     (
     SELECT COUNT(*) 
     FROM quizz_results qr 
     WHERE qr.quizz_id = q.id 
     ) AS total_played, 
     (
     SELECT result 
     FROM qr.quizz_id = q.id 
       AND user_id = 683735 
     ) AS current_user_won 
FROM quizz q