我在使用执行速度非常慢的MySQL查询时遇到了困难。我希望你们中的一些人能够就如何提高查询速度给我一些建议。
这是表结构:
+---------------+------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| MedlemsID | int(11) | NO | MUL | NULL | |
| Medlemsnummer | int(11) | NO | | NULL | |
| Handling | tinyint(1) | NO | | NULL | |
| KlubID | int(11) | NO | | NULL | |
| Klubtype | varchar(5) | NO | | NULL | |
| Tidspunkt | timestamp | NO | MUL | CURRENT_TIMESTAMP | |
| Køn | int(1) | NO | | NULL | |
+---------------+------------+------+-----+-------------------+----------------+
8 rows in set (0.00 sec)
这是查询:
SELECT * FROM (
SELECT *
FROM Handlinger
AS a
WHERE date(Tidspunkt) = curdate()
AND Tidspunkt = (
SELECT max(Tidspunkt)
FROM Handlinger
AS b
WHERE a.MedlemsID = b.MedlemsID
AND a.Klubtype = b.Klubtype
)
)
AS c
WHERE Handling=1
AND KlubID=1
ORDER BY Medlemsnummer ASC
这就是结果:
+-------+-----------+---------------+----------+--------+----------+---------------------+-------+
| id | MedlemsID | Medlemsnummer | Handling | KlubID | Klubtype | Tidspunkt | Køn |
+-------+-----------+---------------+----------+--------+----------+---------------------+-------+
| 24743 | 613 | 10 | 1 | 1 | UK | 2011-08-10 12:14:10 | Pige |
| 24733 | 572 | 11 | 1 | 1 | UK | 2011-08-10 10:45:00 | Pige |
| 24731 | 705 | 13 | 1 | 1 | FK | 2011-08-10 10:31:35 | Dreng |
| 24740 | 409 | 51 | 1 | 1 | FK | 2011-08-10 11:48:19 | Dreng |
| 24757 | 443 | 88 | 1 | 1 | FK | 2011-08-10 15:01:43 | Dreng |
| 24730 | 723 | 89 | 1 | 1 | FK | 2011-08-10 10:30:13 | Dreng |
| 24749 | 465 | 110 | 1 | 1 | FK | 2011-08-10 13:29:40 | Dreng |
| 24720 | 483 | 129 | 1 | 1 | FK | 2011-08-10 10:03:43 | Dreng |
| 24725 | 748 | 181 | 1 | 1 | FK | 2011-08-10 10:12:11 | Dreng |
| 24748 | 540 | 207 | 1 | 1 | FK | 2011-08-10 13:26:54 | Dreng |
+-------+-----------+---------------+----------+--------+----------+---------------------+-------+
10 rows in set (2.95 sec)
我非常感谢你的帮助。
编辑一些描述:
应用程序本身就像俱乐部成员的登记系统。会员每次登录或退出时都会在DB中注册。为了使应用程序有用,它必须在一天中的任何给定时间显示谁在线。所以我的查询是获取当天的所有登录,如果最近的活动是登录,那么它将被输出到应用程序。所有这些都像魅力一样,但如果他们必须等待多秒才能看到谁在线以及谁不在线,那就不是用户友好了。
希望稍微清除我的目标。 :)
答案 0 :(得分:1)
你有没有索引你的桌子?
如果没有,您应该创建两个索引:
首先尝试使用medlemsID,它应该已经好多了。
答案 1 :(得分:1)
你的查询是WAYYYY重载...因为你期望一个特定的日期,我会有一个复合索引
日期(TidSpunkt),处理,KlubID,MedlemsID
然后,尝试以下...由于表使用自动增量,最高的数字意味着最近的日期...因此,我们可以获得每个MedlemsID的最大ID,以便更快地加入那些资格
Select STRAIGHT_JOIN
H1.*
from
( select
H2.MedlemsID,
max( H2.ID ) LastID
from
Handlinger H2
where
date( H2.Tidspunkt ) = curdate()
AND H2.Handling = 1
AND H2.KlubID = 1
group by
H2.MedlemsID ) PreQuery
JOIN Handlinger H1
On PreQuery.LastID = H1.ID
order by
H1.Medlemsnummer ASC
答案 2 :(得分:0)
我不知道你为什么写这些子查询:
SELECT *
FROM Handlinger
AS a
WHERE date(Tidspunkt) = curdate()
AND Tidspunkt = (
SELECT max(Tidspunkt)
FROM Handlinger
AS b
WHERE a.MedlemsID = b.MedlemsID
AND a.Klubtype = b.Klubtype
)
请注意:由于date(Tidspunkt)
短语,您未使用索引。
尝试:
SELECT `a`.* FROM Handlinger AS `a`
INNER JOIN (
SELECT `id` FROM Handlinger WHERE
Tidspunkt >= CONCAT(LEFT(NOW(), 10), ' 00:00:00')
AND Handling=1
AND KlubID=1
) AS jnd USING (`id`)
ORDER BY `a`.Medlemsnummer ASC
答案 3 :(得分:0)
试试这个。相关的子查询总是非常昂贵。您可能需要使用3个Join字段来快速创建密钥。
SELECT a.*
FROM Handlinger as a
JOIN (SELECT medlemsID, KlubType, max(Tidspunkt) as maxTidspunkt
FROM Handlinger
GROUP BY medlemsID, KlubType) as b
ON a.MedlemsID = b.MedlemsID
AND a.KlubType = b.KlubType
AND a.Tidspunkt = b.maxTidspunkt
WHERE a.Handling = 1
AND a.KlubID = 1
AND a.Tidspunkt = curdate()
ORDER BY a.Medlemsnummer ASC