我正在尝试为特定实体创建状态/消息更新页面。用户可以 订阅任意数量的实体,在此页面上您将获得最新信息。 我当前的查询需要一段时间才能运行(1.3+秒,在一个200K行的测试表中), 只抓了50行左右
架构是:
实体:
entity_id, message, timestamp
用户
user_id
订阅
user_id, entity_id
查询是:
SELECT entity.*
FROM entity
INNER JOIN subscription ON subscription.entity_id = entity.entity_id
WHERE subscription.user_id = 1
ORDER BY entity.timetamp DESC
LIMIT 50
数据库方面的问题似乎是这样的:
Copying to tmp table 0.033285
converting HEAP to MyISAM 0.031850
Copying to tmp table on disk 1.177973
Sorting result 0.064075
在订阅表上,我得到以下解释信息:使用索引;使用临时;使用filesort
我正在使用InnoDB表,我在entity_id,user_id和timestamp列上有索引
更新:看来订单可能有所贡献或是问题。我在timestamp列上有一个索引,除此之外,我还能做些什么来更快地获取最新的消息?
更新:当我删除order by子句时,查询会快速运行。 .0006秒vs 1.3。所以我尝试先通过子查询获取数据然后运行order by,但这没有做任何事情。
使用的查询是:
SELECT tbl.* FROM (
SELECT entity.*
FROM entity
INNER JOIN subscription ON subscription.entity_id = entity.entity_id
WHERE subscription.user_id = 1
) as tbl
ORDER BY tbl.timetamp DESC
答案 0 :(得分:0)
您可以尝试此查询:
SELECT entity.* FROM
entity
INNER JOIN
(SELECT *
FROM subscription
WHERE user_id = 1
) AS subscriptions_for_user ON subscriptions_for_user.entity_id = entity.entity_id
ORDER BY entity.timetamp DESC
LIMIT 50
通过这种方式,您只需加入与user_id相对应的订阅,即少量数据。
答案 1 :(得分:0)
在实体表中,您需要一个单索引,该索引涵盖 entity_id和时间戳,按顺序。如果这是主键,那就最好了。在订阅表上,您需要一个索引 user_id和entity_id,按顺序。这些索引必须包含同一索引中的两列。
完成后,您要确保让MySql拥有足够的RAM,以便能够将RAM 和索引保存在RAM中,然后运行一些示例在进行实际基准测试之前,先查询“预热”数据库缓存。
我还建议您想要一个与实体表分开的消息表,它实际上是您将在此处查看的消息表。
答案 2 :(得分:0)
只是确保你并不意味着每个EntityID的TOP 50,在这种情况下,查询将是非常不同的。 在查询中使用LIMIT的方式最多意味着您将获得按时间戳排序的50行。
如果第二个为真,那么您可以仅在第一次过滤大表。 此外,如果您在查询中使用“Order By”,请尝试提供可在WHERE条件中使用的常量/列表。 这样,数据库引擎可以更有效地利用索引。
您需要的索引。
表实体:
TimeStamp DESC, EntityID ASC, Message ASC
表订阅:
User_id,entity_ID
尝试此查询
SET @Rownum=1
SET @PValue=''
SELECT Entity_ID,Message,TIMESTAMP
FROM
(
SELECT
@Rownum:=IF(@Timestamp=Timestamp, @Rownum+1,1) AS RowNumber
,Entity_ID
,MESSAGE
,TimeStamp
@Timestamp=@Timestamp AS DummyTimeStamp
FROM Enitty
WHERE Entity_ID IN (SELECT Entity_ID FROM Subscription WHERE USER_ID = 1)
ORDER BY Timestamp DESC
)qry
WHERE RowNumber <=50