我有一个相对较大的4深度关系数据设置,如下所示:
client_applications:(可能有1000‘S的记录)
成型机- ...
成型机- account_id
成型机- deleted_at
client_application_versions:(可能有10,000's的记录)
成型机- ...
成型机- client_application_id
成型机- deleted_at
cloud_logs:(可能有100万S的记录)
再来.
成型机- client_application_version_id
成型机- deleted_at
logs:(可能有10亿,000,000‘S的记录)
成型机- ...
成型机- cloud_log_id
成型机- time_stamp
成型机- deleted_at
我还在开发中,所以结构和设置不是一成不变的,但我认为它是好的。使用Rails 3.2.11和InnoDB MySQL。数据库中填充了一小组数据(与最终的db大小相比) (logs只有70万行),我有4个查询(其中3个有问题)来检索日志。
account_id、client_application_id、client_application_version_id的限制(超过100秒)account_id、client_application_id限制(超过100秒)account_id限制(超过100秒)以下是解释语句。我已经对所有适用的字段建立了索引。复制...id表上的各个logs字段以防止联接是否更好?或者,当我问这些问题的时候,是不是缺少了一些神奇的酱汁?我以前从来没有处理过这么多的数据,所以也许我处理设置和查询的标准方法就是不扩展?如何更改设置或语句以使这些查询在合理的时间内返回?
更新
我在日志表上添加了几个组合索引,并在时间上稍微减少了一点。以下是解释就是为了这个。我的结论是,订单方法是延迟的原因。删除order by timestamp desc将导致查询在一秒钟左右内返回。因此,新的问题是,为什么在时间戳上建立索引时,运行这个查询还需要超过一分钟的时间?
更新2
使用子查询将100个id的性能提高到14秒,但这仍然太长了。到目前为止,我尝试过的优化都缩短了一些时间,但我觉得它们并没有从根本上解决问题。用于子查询方法的这是解释。
发布于 2013-01-11 17:38:44
这里不是DBA或MySQL专家,但让我们试试:)。因此,让我们使用您的第二个查询--比第一个查询小一点--并简化表名。
我们有如下内容:(LO =LO,CL = cloud_logs,CAV = client_application_versions,CA = client_applications)
SELECT LO.* FROM LO
INNER JOIN CL ON CL.id = LO.cloud_log_id
INNER JOIN CAV ON CAV.id = CL.client_application_version_id
INNER JOIN CA ON CA.id = CAV.client_application_id
WHERE (LO.deleted_at IS NULL)
AND (CA.account_id = '3')
AND (CA.id = '5')
ORDER BY timestamp DESC LIMIT 100 OFFSET 0所以你说大约需要100秒钟,对吧?
当你说:
我已经对所有适用的字段建立了索引。
但我相信这就是缺陷所在。你没有那么多的连接,你可能有70亿个数据,或者仅仅700个,如果索引被正确地考虑的话,这应该是很好的表现,我认为这可能是因为索引不好而影响性能的顺序/限制。
1你试过:
SELECT LO.* FROM LO WHERE (LO.deleted_at IS NULL)或
SELECT * FROM CA WHERE (CA.account_id = '3') AND (CA.id = '5')看看这些请求是如何及时执行的,如果这两个表一切正常的话?
[2]你也有索引时间戳吗?索引您正在进行的"order“列也是至关重要的。实际上,您甚至应该考虑您的数据以及您要查询的每个数据有多少值。这里很好地解释了这一点:http://www.mysqlperformanceblog.com/2006/09/01/order-by-limit-performance-optimization/,肯定会对您有所帮助。
3.根据我几分钟前在MySQL上所读到的内容,您也可以尝试MySQLCheck,看看您的表中的所有内容是否都还好,如果您认为索引是ok的,http://dev.mysql.com/doc/refman/5.0/en/mysqlcheck.html。我知道,在早期版本的甲骨文中,我们必须在创建索引之后计算统计数据,也许这里类似的东西?
希望这能有所帮助。
编辑: 12/01/13在评论后
好吧,很高兴看到你已经把时间除以4,但事实上25s太长了。
[1]您是否尝试过通过创建一个有意义的索引来处理索引,如Peter (http://www.mysqlperformanceblog.com/2006/09/01/order-by-limit-performance-optimization/)所解释的那样?比如索引(CA.account_id,CA.id,时间戳)等等?
[2]当您按/限制按以下方式处理订单时,需要多长时间?
SELECT LO.* FROM LO
INNER JOIN CL ON CL.id = LO.cloud_log_id
INNER JOIN CAV ON CAV.id = CL.client_application_version_id
INNER JOIN CA ON CA.id = CAV.client_application_id
WHERE (LO.deleted_at IS NULL)
AND (CA.account_id = '3')
AND (CA.id = '5') 检查这是否是按/限制影响您的性能的订单?
3/在第2种情况下,您可以尝试这样的方法:
SELECT LO.* FROM LO
INNER JOIN CL ON CL.id = LO.cloud_log_id
INNER JOIN CAV ON CAV.id = CL.client_application_version_id
INNER JOIN CA ON CA.id = CAV.client_application_id
INNER JOIN
(
SELECT LO.id FROM LO
INNER JOIN CL ON CL.id = LO.cloud_log_id
INNER JOIN CAV ON CAV.id = CL.client_application_version_id
INNER JOIN CA ON CA.id = CAV.client_application_id
WHERE (LO.deleted_at IS NULL)
AND (CA.account_id = '3')
AND (CA.id = '5')
ORDER BY timestamp DESC LIMIT 0,100
) AS PERF ON PERF.id = LO.id将LO.id替换为用日志表示的列(我想您有某种日志id )。这是基于:http://explainextended.com/2009/10/23/mysql-order-by-limit-performance-late-row-lookups/注释,您可以更改限制0,100并保留偏移量关键字,以防止需要它(如果需要PostgreSQL兼容性的话)。
发布于 2019-10-08 10:02:57
不确定这个帮助,但在我的例子中,有带有3mil行的表。非常简单的连接或联合或循环查询都非常慢。仅对20行结果进行测试和测试,我只需输入一个简单的命令来查询
力指数(one_colum_indexed)
如果您的表中有多个索引字段,那么您必须逐个测试哪个one_colum_indexed,以查找哪一个是最好的。
所有的信用都在这里,使用强制索引加快查询速度
https://dba.stackexchange.com/questions/31636
复制相似问题