0

所以,我有一个包含 500 万条记录的数据库,它存储了问答网站的信息。结构是...

question, qid, quserid, answer, auserid;

(qid 是问题的 ID 号)

我试图找到所有有特定用户未回答的问题的用户,并按特定用户未回答的问题数量对其进行排序。这是我的查询:

SELECT quserid, COUNT(quserid)
FROM `qanda` 
WHERE qid NOT IN (SELECT qid FROM `qanda` WHERE auserid='myusername' GROUP BY qid) 
GROUP BY quserid 
ORDER BY COUNT(quserid) DESC 
LIMIT 0,1000;

问题:它需要 2 多个小时,而时钟仍在滴答作响!有人知道如何加快这个数据库的速度吗?我认为数据库中存在错误或其他东西,通常最多只需要30秒即可完成一个简单的查询,所以这有点荒谬。任何人都知道任何调整?可能是对配置文件的简单更改或其他什么?

…………

这是我刚刚复制和粘贴的数据库中的一些数据。抱歉没有格式化。

you could have any one person in the entire wor...  greendaystud    ive got the person i want...its great...because sh...   •glitter•rock•  191437  If you could have any one person in the entire wor...   just~another~slave2tears    i already got em
                            •glitter•rock•  191437  If you could have any one person in the entire wor...   korn_chick2007  matt or chris... i have feelings for them
                            •glitter•rock•  189555  why are you so sexy?
    just~another~slave2tears    my b/f says i am...i dun tink so tho
                            •glitter•rock•  189555  why are you so sexy?
    korn_chick2007  im not
                            •glitter•rock•  189555  why are you so sexy?
    MyKool-AidsSexy     i dont think i am
                            †brokengirl†    115228  If you are supposed to expect the unexpected,
doe...  death-tone  yip
                            †brokengirl†    115228  If you are supposed to expect the unexpected,
doe...  _doieverknowwhoiam_     you know whats weird? my friend sandy says that a ...
                            †brokengirl†    115228  If you are supposed to expect the unexpected,
doe...  Cute_Physco_kitty   Pretty much..
                            †brokengirl†    115228  If you are supposed to expect the unexpected,
doe...  Leslie02    WHAT! OK, now im confused!
                            †brokengirl†    114995  Why does my listerine taste like sausage this
mor...  death-tone  what's listerine?
                            †brokengirl†    114995  Why does my listerine taste like sausage this
mor...  _doieverknowwhoiam_     i don't know, and maybe it's jut me bu...
                            †brokengirl†    114995  Why does my listerine taste like sausage this
mor...  darksunofdeath  How old is the listerine pack?
                            †brokengirl†    114995  Why does my listerine taste like sausage this
mor...  Cute_Physco_kitty   uhh... New brand of Listerine?
    †brokengirl†    114995  Why does my listerine taste like sausage this
mor...  Leslie02    did you have sausage for breakfast?     †brokengirl†    104305  What should I name my pinky toe on my left
foot?¿...   death-tone  "Pinkytoe"        

而且,预期的输出,使用方便的列标题......

Questioner User ID | Number of questions asked by the Questioner that were unanswered by 'myuserid'

Greenbay Packer | 6
DollyDoll | 63
PsychoticPokemon | 62
HelloKitty | 61
GreenDayFan | 60

...

IDontAskManyQuestion | 2<br>
WhatsAQuestion? | 1<br>

这是解释输出

> mysql-> EXPLAIN
>     ->
>     -> SELECT quserid, COUNT(quserID)
>     -> FROM `qanda`
>     -> WHERE qid NOT IN (SELECT qid FROM `qanda` WHERE auserid='boxocereal' GROU P BY qid)
>     -> GROUP BY quserid
>     -> ORDER BY COUNT(quserid) DESC
>     -> LIMIT 0,1000;
> 

+----+--------------------+-------+------+---------------+------+---------+-----
> -+---------+----------------------------------------------+ | id | select_type        | table | type | possible_keys | key  | key_len |
> ref  | rows    | Extra                                        |
> +----+--------------------+-------+------+---------------+------+---------+-----
> -+---------+----------------------------------------------+ |  1 | PRIMARY            | qanda | ALL  | NULL          | NULL | NULL    |
> NULL  | 3167995 | Using where; Using temporary; Using filesort | |  2
> | DEPENDENT SUBQUERY | qanda | ALL  | NULL          | NULL | NULL    |
> NULL  | 3167995 | Using where; Using temporary; Using filesort |
> +----+--------------------+-------+------+---------------+------+---------+-----
> -+---------+----------------------------------------------+ 2 rows in set (0.02 sec)
> 
> mysql->
4

4 回答 4

2

好的,我有一个将其转换为 JOIN 而不是子查询的想法。该技术实际上是在有用户的地方加入回答该用户(因为这从根本上更有效),然后从最终结果中排除这些问题(在 HAVING 中)。有可能这可以进一步改进(我没有测试过,但 IS NULL 检查可能会移到 WHERE 子句中)。

这能让你到达你想去的地方吗?

SELECT question.quserid, COUNT(question.quserid) as num_questions
FROM qanda as question 
LEFT OUTER JOIN qanda as answers 
  ON question.qid = answers.qid AND answers.auserid = 'myusername'
GROUP BY question.quserid
ORDER BY num_questions DESC
HAVING answers.auserid IS NULL;

编辑:多一点解释,以防万一这很接近并且其他人可以帮助将这个想法改进为解决方案。

基本上,查询的主要部分将只选择每个问题一次(LEFT OUTER),然后对于感兴趣的用户已回答的问题,它还将选择已加入的列。这使我们处于候选结果集中所有问题的状态,“标志”附加到我们不感兴趣的问题(即非空连接列)。然后我们对包含非空连接数据的行进行分组并拒绝。

于 2012-06-24T08:36:02.230 回答
0

根据输出,如果发生全表扫描,请尝试找出可以实施索引的候选对象。

于 2012-06-24T08:35:01.040 回答
0

也试试这个:

SELECT quserid, COUNT(*) AS num
FROM qanda
WHERE qid NOT IN 
        ( SELECT qid
          FROM qanda 
          WHERE auserid = 'user2' 
        )  
GROUP BY quserid 
ORDER BY num DESC 
LIMIT 0,1000 ;

您肯定需要为任何这些变体添加索引以提高效率。

(qid, quserid, auserid)钥匙PRIMARY吗?是吗UNIQUE(我想它应该是两者之一。

上的索引(quserid, qid)也会有所帮助(如果您的表使用 InnoDB 引擎)。

于 2012-06-24T09:18:15.143 回答
0

参考@ctrahey 的答案,我已经更改了查询并得到了解决方案,因为@ctrahey 没有像你这样给出输出,如此处所示

你能试试,让我知道这是否更快?

SELECT question.quserid, COUNT(question.quserid) as num_questions
FROM qanda as question 
LEFT OUTER JOIN qanda as answers 
  ON question.qid = answers.qid AND answers.auserid = 'user2'
WHERE answers.auserid IS NULL
GROUP BY question.quserid
ORDER BY num_questions DESC;

另见sqlfiddle。您的查询和上述查询给出相同的输出。

希望这是你想要的。

于 2012-06-24T09:13:50.870 回答