我在PHP中使用PDO的MySQL,我有一个SQL查询,它按预期工作。但是,我关心的表现,并想知道我是否可以改善我的查询。我还问,是因为我想增益SQL的一些背景知识。两个SQL查询 - 性能差异?
比方说,我有一个有数等于领域(和一些其他信息,这是不同各表)两个表:
table `blog_comments`: id, userid (int) | timestamp (int) | content (varchar) | other
table `projects_comments`: id, userid (int) | timestamp (int) | content (varchar) | other
领域id
是主键,userid + timestamp
有两个表中的索引和时间戳是简单地用10(整数)长度unixtime。
举一个简单的垃圾邮件防护,我从提交新的评论阻止用户(无论博客,项目或其他任何东西),直至自他最后评论60秒已经过去了。要做到这一点,我得到的是用户从所有意见表的最新时间戳。
这是我工作查询:
SELECT MAX(`last_timestamp`) AS `last_timestamp`
FROM
(
SELECT `userid`, max(`timestamp`) AS `last_timestamp`
FROM `blog_comments`
GROUP BY `userid`
UNION ALL
SELECT `userid`, max(`timestamp`) as `last_timestamp`
FROM `projects_comments`
GROUP BY `userid`
) AS `subquery`
WHERE `userid` = 1
LIMIT 0, 1;
正如你可以看到,我用GROUP BY的子查询内,并在主查询我只是过滤的userid(在这种情况下:1)。优点:我只需要合格用户标识一次作为参数。
现在,我对SQL如何正确工作感兴趣。我认为这将是这样的:SQL首先由用户ID进行子查询,组所有的现有行和返回整个设置到主查询,然后应用where子句中找到所需要的用户ID。这对我来说似乎是一个巨大的性能泄漏。
所以我想略有更改查询:
SELECT max(`last_timestamp`) AS `last_timestamp`
FROM
(
SELECT max(`timestamp`) AS `last_timestamp`
FROM `blog_comments`
WHERE `userid` = 1
UNION ALL
SELECT max(`timestamp`) as `last_timestamp`
FROM `projects_comments`
WHERE `userid` = 1
) AS `subquery`
LIMIT 0, 1
现在我必须通过用户ID两次了,还是一整套的行会抬头为给定的用户ID。我不知道这真的是改善的表现。
我没有任何大的数据量还没有真正测试它,也许我会做一些测试场景以后。我会真正有兴趣知道这些表中有多少数据集时是否会有所不同?
希望任何想法,信息和提示,在此先感谢。
编辑:第一查询
MySQL的讲解:第二查询
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4 Using where
2 DERIVED blog_comments range NULL userid 8 NULL 10 Using index for group-by
3 UNION projects_comments index NULL userid 12 NULL 6 Using index
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
MySQL的解释:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
2 DERIVED NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
3 UNION NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
的确,查询看起来神秘嘿嘿,但我看到它是如何工作的。感谢您提醒我解释'功能。现在我看到,在第一个查询中,首先执行WHERE,这是否意味着GROUP BY将已经提到给定的userid? – Francodi
@Francodi。 。 。不,我删除它。当我编辑代码时,这是代码碎片。 –
对不起,我的意思是我提到的两个问题中的第一个。 'explain'告诉我主查询的WHERE在MySQL进入子查询之前执行,这就是为什么我会问'userid'是否已经在GROUP BY中考虑了? – Francodi