con*_*are 6 mysql innodb index database-design scalability
我有一个相对较大的 4-deep 关系数据设置,如下所示:
client_applications: (可能有 1,000 条记录)
- ...
- account_id
-deleted_at
client_application_versions:(可能有 10,000 条记录)
- ...
- client_application_id
-deleted_at
cloud_logs:(可能有 1,000,000 条记录)
- ...
- client_application_version_id
-deleted_at
logs:(可能有 1,000,000,000 条记录)
- ...
- cloud_log_id
- time_stamp
-deleted_at
我仍在开发中,所以结构和设置不是一成不变的,但我认为设置没问题。使用 Rails 3.2.11 和 InnoDB MySQL。数据库充满了一个小的(与最终的数据库大小相比)数据集(logs只有 700,000 行)我有 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导致查询在一秒钟左右返回。所以新的问题是为什么当索引时间戳时,运行这个查询仍然需要超过一分钟的时间?
虽然不是 DBA 或 MySQL 专家,但让我们尝试一下:)。因此,让我们采用第二个查询(比第一个查询小一些)并简化表名称。
我们有这样的东西:(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
Run Code Online (Sandbox Code Playgroud)
所以你说大约需要 100 秒,对吗?
当你说 :
我已经拥有所有适用字段的索引。
但我相信这就是缺陷所在。你没有那么多的连接,你可能有 70 亿个数据或只有 700 个数据,如果正确地考虑了索引,那么应该表现良好,而且我认为这可能是 order by / limit 扰乱了你的性能,因为它的性能很差索引。
1/ 你尝试过吗:
SELECT LO.* FROM LO WHERE (LO.deleted_at IS NULL)
Run Code Online (Sandbox Code Playgroud)
或者
SELECT * FROM CA WHERE (CA.account_id = '3') AND (CA.id = '5')
Run Code Online (Sandbox Code Playgroud)
如果这两个表一切正常,看看这些请求如何及时执行?
2/你也索引了时间戳吗?对您要进行“排序依据”的列进行索引也很重要。事实上,您甚至应该考虑您的数据以及您正在查询的每个数据将有多少个值。这有很好的解释:http://www.mysqlperformanceblog.com/2006/09/01/order-by-limit-performance-optimization/ ,肯定会对您有所帮助。
3/根据我几分钟前在MySQL上读到的内容,如果您认为索引没问题,您也可以尝试MySQLCheck,看看您的表是否一切正常 http://dev.mysql.com/doc/refman/5.0/ en/mysqlcheck.html。我知道在旧版本的 oracle 中,我们必须在创建索引后计算统计数据,也许这里有类似的东西?
希望这可以帮助。
[编辑:2013 年 12 月 1 日评论后]
好吧,很高兴看到你已经将时间除以 4,但确实 25 秒太长了。
1 /您是否尝试过通过创建一个有意义的索引来使用索引,就像Peter在这里解释的那样(http://www.mysqlperformanceblog.com/2006/09/01/order-by-limit-performance-optimization/) ?就像(CA.account_id、CA.id、时间戳)等上的索引一样?
2/当您像下面这样摆脱 order by / limit 时需要多长时间?
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')
Run Code Online (Sandbox Code Playgroud)
检查这是否会是影响您性能的 order by/limit ?
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
Run Code Online (Sandbox Code Playgroud)
您将 LO.id 替换为对 Logs 有意义的列(我想您有某种 Logs id 。这是基于: http: //explainextended.com/2009/10/23/mysql-order-by- limit-performance-late-row-lookups/ 请注意,您可以更改 LIMIT 0,100 并保留 OFFSET 关键字,以备不时之需(如果需要 PostgreSQL 兼容性)。
| 归档时间: |
|
| 查看次数: |
9428 次 |
| 最近记录: |