【问题标题】:Prepared Statements, MyISAM with 100 million records and Caching on MySQLPrepared Statements,拥有 1 亿条记录的 MyISAM 和 MySQL 上的缓存
【发布时间】:2016-06-04 19:46:00
【问题描述】:

我有 10 个大型只读表。我做了很多格式相同但参数不同的查询,例如:

SELECT 'count' FROM table1 WHERE x='SOME VARIABLE';
SELECT 'count' FROM table1 WHERE x='SOME OTHER VARIABLE';
...
SELECT 'count' FROM table2 WHERE x='' AND y='';
SELECT 'count' FROM table2 WHERE x='' AND y='';
...
SELECT 'count' FROM table3 WHERE x='' AND y='' AND z='';

每个查询使用的变量都不同,所以我几乎从不两次执行相同的查询。 MySQL端的查询缓存和行缓存会浪费并且应该禁用它们是否正确?表缓存似乎是一件好事。

在客户端,我使用的是我认为很好的准备好的语句。如果我启用 Prepared 语句缓存(通过 Slick),但由于参数如此多变,这不会影响我的性能吗?我还能做些什么来优化我的表现吗?

是否应该关闭自动提交,因为我只进行选择并且永远不需要回滚?

【问题讨论】:

  • 为什么不首先关注您的主要访问途径并确认您的索引策略是否平衡。在 upsert 的缓慢与读取的速度之间取得了很好的平衡。顺便说一句,准备好的语句通常不被认为是一种性能提升机制,就像它们用于 1) 可读性 2) 注入安全性 3) 类型安全性一样。我会冒险猜测 95% 的准备好的语句没有被重用
  • 对于准备好的语句绑定的速度,它们很慢。我为什么这么说?由于测试。通过使用准备好的语句,使用其他策略尤其是处理大型集合可以快 50 倍以上。
  • 我不知道,我想我混淆了 p.s.使用准备好的语句进行缓存。谢谢你。我的指数策略是可靠的。我正在考虑压缩/打包我的表并将 var-char 列转换为性能更高的类型。
  • 您打算使用哪个引擎?表的大小是多少(我们是在谈论数百个条目,还是这些数千/数百万个条目)?条件属性x,y,z是否分别包含每个表的主键?
  • 只是不要试图过度设计某些东西并解决你没有的问题。对我来说,数据摄取率至关重要,所以我别无选择。对于 onsy-twosy 行(插入),我会忽略我的胡言乱语。

标签: mysql database caching jdbc slick


【解决方案1】:

鉴于您使用的是 MYISAM 引擎并且拥有具有数亿个活动行的表,因此我不会太在意如何查询缓存(由于您的复杂性低,这很可能是最少的问题),但更关注数据库中数据的正确组织:

  • Prepared Statements 完全没问题。不要一遍又一遍地准备声明可能会有所帮助。相反,只需使用一组新的参数值重用现有的准备好的语句(某些环境甚至允许在客户端存储准备好的语句)。但是,这主要只是节省时间,而时间正在查询缓存中使用。由于您的查询的复杂性非常低,因此可以假设这不会是最大的时间消耗者。
  • 然而,Key Caching(也称为密钥缓冲)是 - 正如其名称所暗示的 - 游戏的关键! MySQL 的大多数 DB 配置在该区域中都存在错误值,因为缓冲区太小了。简而言之,键缓存确保可以在主内存中访问对数据的引用(例如在您的索引中)。如果它们不在内存中,则需要从磁盘中检索它们,这很慢。要查看您的键缓存是否有效,您应该在系统处于负载状态时观察键命中率。 https://dba.stackexchange.com/questions/58182/tuning-key-reads-in-mysql 详细解释了这方面的详细信息。
  • 如果缓存变大或由于其他表的使用而频繁移位,为您的表创建自己的键缓存可能会有所帮助。详情请见https://dev.mysql.com/doc/refman/5.5/en/cache-index.html
  • 如果您总是通过相同的属性访问表的大部分,使用ALTER TABLE ... ORDER BY expr1, expr2, ... 更改磁盘上数据存储的顺序可能是有意义的。有关此方法的详细信息,另请参阅https://dev.mysql.com/doc/refman/5.5/en/optimizing-queries-myisam.html
  • 避免使用可变长度列,例如VARCHARBLOBTEXT。它们可能有助于节省一些空间,但特别是比较它们的值可能会变得很耗时。但是请注意,MySQL 已经有一个此类类型的列将切换到 Dynamic 列模式。
  • 在大量数据更改后运行ANALYZE TABLE 以使统计信息保持最新。如果您删除了大片区域,可以OPTIMIZE TABLE,帮助确保阅读时没有需要跳过的大间隙。
  • 如果您不需要回复,请使用INSERT DELAYED 异步写入更改。如果在同一时间点周围还有其他 SELECT 语句,这将大大提高您的性能。
  • 或者,如果您需要回复,您可以使用INSERT LOW_PRIORITY。那么与INSERT 相比,并发SELECTs 的执行是首选。这可能有助于减轻一点事实的痛苦,即 MyISAM 仅支持表级锁定。
  • 您可以尝试为您的查询提供Index Hints,尤其是当您的表上有多个相互重叠的索引时。您应该尝试使用宽度最小但仍覆盖最多属性的索引。 但是,请注意,在您的情况下,影响必须非常小:您没有排序/分组或加入,因此查询优化器应该已经非常擅长找到最好的。只需在您的 SELECT 语句中使用 EXPLAIN 即可检查所使用的索引选择是否合理。

简而言之,Prepared Statements 完全没问题。密钥缓存是关键 - 您还可以做一些其他事情来帮助 MySQL 处理大量数据。

【讨论】:

    猜你喜欢
    • 2018-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-25
    • 2011-12-13
    相关资源
    最近更新 更多