[英]How to improve performance of this sql query?
(我在PHP和MySQL上工作)
这是一种情况:通过ajax请求,我每隔10秒检查一次用户所属日历中是否有新内容。
每个日历都有一些要检查的内容(w / e是日历或其他元素,但是在这种情况下,它是日历),所以我做了一个“大”查询以返回每个日历的所有数据,并且我用php处理,然后用js处理(弹出通知或w / e)。
要检查的三件事:
我是这样做的:
SELECT DISTINCT
ci.ci_cid as c_id,
MAX(cc.cc_timestamp) as chat_lastmsg, umchat.um_value as chat_lastview,
MAX(cr.cr_id) as request_id,
cmodif.cm_value as modification_timestamp,
umodif.um_value as modification_view
FROM c_individuals as ci
LEFT JOIN c_chats as cc ON cc.cc_cid = ci.ci_cid
LEFT JOIN u_metas as umchat ON (umchat.um_uid = ci.ci_ciuid AND umchat.um_cid = ci.ci_cid AND umchat.um_name = "chat_last_view")
LEFT JOIN c_requests as cr ON (cr.cr_cid = ci.ci_cid AND cr.cr_answer = "0")
LEFT JOIN c_metas as cmodif ON (cmodif.cm_cid = ci.ci_cid AND cmodif.cm_name = "last_modifications")
LEFT JOIN u_metas as umodif ON (umodif.um_uid = ci.ci_uid AND umodif.um_cid = ci.ci_cid AND umodif.um_name = "last_view")
WHERE ci.ci_uid = :u_id
GROUP BY ci.ci_cid
c_individuals
表具有日历中的用户。 u_metas
表具有用户的元数据,其中包括um_uid
(用户ID), um_cid
(与元数据有关的日历ID), um_name
(元数据的名称), um_value
(元数据的值) c_requests
表包含请求信息(u_id,c_id,答案和内容) 我的查询给了我我想要的东西,意思是:
0 =>
array (size=6)
'c_id' => string '50' (length=2)
'chat_lastmsg' => null
'chat_lastview' => null
'request_id' => null
'modification_timestamp' => string '1488878397.703508' (length=17)
'modification_view' => string '1488877914.048585' (length=17)
1 =>
array (size=6)
'c_id' => string '51' (length=2)
'chat_lastmsg' => string '1485326492' (length=10)
'chat_lastview' => string '1488470529' (length=10)
'request_id' => null
'modification_timestamp' => string '1488878397.703508' (length=17)
'modification_vue' => string '1488878065.811320' (length=17)
但是老实说,我认为这有点慢。 如果不进行处理,那么仅要获取查询结果,就需要3.5秒的时间来重复进行1000次。
没什么大不了的,但是对于潜在的大量用户,此查询会重复很多次。
所以我的问题是:有什么办法可以改善它,或者我对此有好处吗?
谢谢您的时间,对不起,我的英语不好。
您发布的查询没有发现任何问题,只是因为您正在执行GROUP BY
所以您不需要DISTINCT
。 另外,请确保在JOIN ON
条件和WHERE
条件中使用的列上具有正确的索引。
更多的是系统/数据库设计问题,而不是查询设计。
该查询看起来足够了,并给出了您期望的结果,所以很好(尽管不确定为什么需要LEFT联接-但这取决于您的数据。)
在系统设计空间中要考虑的事项:
对数据库结构进行非规范化-每当您输入c_chat或c_request等时,您都可能希望针对用户存储最新的时间戳记,因此您不进行联接-这非常慢。
您可以从更靠近服务器的缓存(例如Memcache)中受益吗? 如果您有很多请求,那么在数据库运行缓慢的情况下,可能需要调查一下。 如果要对数据库进行非规范化,则可能不需要缓存。
如果您不仅使用Id,还可以索引在WHERE中用作过滤器的任何内容
作为记录,
我终于找到了更快的东西(在我的“基准测试”中,它快了五到七倍)。
事实是,我不需要获取信息(日期等),我只想知道是否有新内容,因为用户上次(无论何时,何时发布)都看到了它。
所以我做了这个(用法语,请不要打扰):
SELECT
ci.ci_cid as c_id,
(SELECT COUNT(cc_id)
FROM c_chats
LEFT JOIN u_metas ON um_nom = "chat_derniere_vue"
WHERE cc_cid = ci.ci_cid AND um_uid = ci.ci_uid AND um_cid = ci.ci_cid AND CAST(cc_timestamp as decimal) > CAST(um_valeur as decimal)
) as chat,
(SELECT COUNT(cr_id)
FROM c_requetes
WHERE cr_cid = ci.ci_cid AND ci.ci_ustatut = "titulaire" AND cr_reponse = "0"
) as notifications,
(SELECT COUNT(cm_cid)
FROM c_metas
LEFT JOIN u_metas ON um_nom = "derniere_vue"
WHERE um_uid = ci.ci_uid AND um_cid = ci.ci_cid AND cm_cid = ci.ci_cid AND cm_nom = "derniere_modification_periodes" AND CAST(cm_valeur as decimal) > CAST(um_valeur as decimal)
) as modifications
FROM c_individus as ci
WHERE ci.ci_uid = :u_id
GROUP BY ci.ci_cid
通过这种方式, chat
给出了带有新消息的聊天次数, notifications
给出了未应答请求的数量, modifications
给出了带有新日期的日历的数量。
和“多田”!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.