我正在考虑将来自JVM的一些JMX数据存储在许多服务器上大约90天。此数据将是堆大小和线程数等统计信息。这意味着其中一个表将拥有大约3.88亿条记录。
根据这些数据,我正在构建一些图表,以便您可以比较从Mbeans检索到的统计数据。这意味着我将使用时间戳以一定间隔抓取一些数据。
所以真正的问题是,是否有优化表或查询,以便您可以在合理的时间内执行这些查询?
谢谢,
约什
答案 0 :(得分:9)
你可以做几件事:
答案 1 :(得分:2)
3条建议:
P.S。对于时间戳,您可能遇到性能问题 - 取决于MySQL如何在内部处理DATETIME和TIMESTAMP,将时间戳存储为整数可能更好。 (自1970年以来#secs或其他)
答案 2 :(得分:2)
嗯,首先,我建议您使用“离线”处理来生成“图形就绪”数据(对于大多数常见情况),而不是尝试按需查询原始数据。
答案 3 :(得分:1)
如果您使用的是MYSQL 5.1,则可以使用新功能。 但要注意它们包含很多错误。
首先你应该使用索引。 如果这还不够,您可以尝试使用分区来拆分表。
如果这也不起作用,您也可以尝试负载平衡。
答案 4 :(得分:1)
一些建议。
您可能会对这些内容运行聚合查询,因此在将数据加载到表中之后(或同时),您应该预先聚合数据,例如按小时预先计算总计,或者按用户或者按周,无论如何,你都明白了,并将其存储在用于报告图表的缓存表中。如果你可以将数据集缩小一个数量级,那么,对你有好处!
这意味着我将使用时间戳以一定间隔抓取一些数据。
这意味着您只使用过去X天的数据?
如果要删除几千万行,从表中删除旧数据可能会非常慢,分区很适合(只需删除旧分区)。它还将来自同一时间段的所有记录组合在磁盘上,因此它的缓存效率更高。
现在如果你使用MySQL,我强烈建议使用MyISAM表。你没有防碰撞或交易,锁定是愚蠢的,但表的大小比InnoDB小得多,这意味着它可以适应RAM,这意味着更快的访问。
由于大型聚合可能涉及大量相当顺序的磁盘IO,因此像RAID10(或SSD)这样的快速IO系统是一个优势。
无论如何都要优化表或查询,以便您可以执行这些查询 在合理的时间内?
这取决于表和查询;如果不了解更多,就无法提出任何建议。
如果您需要具有大聚合和连接的复杂报告查询,请记住MySQL不支持任何奇特的JOIN,哈希聚合或其他任何有用的东西,基本上它唯一能做的就是嵌套循环索引扫描,这是如果涉及到一些随机访问,那么在缓存的表上表示良好,而在其他情况下则非常糟糕。
我建议你用Postgres测试。对于大型聚合,更智能的优化器确实运行良好。
示例:
CREATE TABLE t (id INTEGER PRIMARY KEY AUTO_INCREMENT, category INT NOT NULL, counter INT NOT NULL) ENGINE=MyISAM;
INSERT INTO t (category, counter) SELECT n%10, n&255 FROM serie;
(系列包含16M行,n = 1 .. 16000000)
MySQL Postgres
58 s 100s INSERT
75s 51s CREATE INDEX on (category,id) (useless)
9.3s 5s SELECT category, sum(counter) FROM t GROUP BY category;
1.7s 0.5s SELECT category, sum(counter) FROM t WHERE id>15000000 GROUP BY category;
在像这样的简单查询中,pg的速度提高了2-3倍(如果涉及复杂的连接,差异会大得多)。
答案 5 :(得分:0)
限制1获取唯一行时 SELECT * FROM user WHERE state ='Alabama'//错误 SELECT 1 FROM user WHERE state ='Alabama'LIMIT 1
索引搜索字段 索引不仅适用于主键或唯一键。如果您要搜索的表中有任何列,则几乎总是将它们编入索引。
索引并使用相同的列类型进行连接 如果您的应用程序包含许多JOIN查询,则需要确保您加入的列在两个表上都已编制索引。这会影响MySQL内部优化连接操作的方式。
不按RAND()排序() 如果您确实需要从结果中随机排列,那么有更好的方法可以实现。虽然它需要额外的代码,但是你可以防止随着数据的增长而出现指数恶化的瓶颈。问题是,MySQL必须对表中的每一行执行RAND()操作(它需要处理能力),然后才对其进行排序,只给你一行。
在VARCHAR上使用ENUM ENUM型柱非常快速和紧凑。在内部,它们像TINYINT一样存储,但它们可以包含和显示字符串值。
如果可以,请使用NOT NULL 除非您有非常具体的理由使用NULL值,否则应始终将列设置为NOT NULL。
“NULL列需要行中的额外空间来记录它们的值是否为NULL。对于MyISAM表,每个NULL列需要额外一位,向上舍入到最接近的字节。”
将IP地址存储为UNSIGNED INT 在查询中,您可以使用INET_ATON()将IP转换为整数,将INET_NTOA()反之亦然。 PHP中也有类似的函数,叫做ip2long()和long2ip()。