38 | 都说InnoDB好,那还要不要使用Memory引擎?
38 | 都说InnoDB好,那还要不要使用Memory引擎?
讲述:林晓斌
时长14:00大小12.84M
内存表的数据组织结构
hash 索引和 B-Tree 索引
内存表的锁
数据持久性问题
小结
上期问题时间
赞 47
提建议
精选留言(31)
- 放2019-02-08老师新年快乐!过年都不忘给我们传授知识!
作者回复: 新年快乐🤝
24 - salt2019-02-08新年好! 课后作业:在备库配置跳过该内存表的主从同步。 有一个问题一直困扰着我:SSD以及云主机的广泛运用,像Innodb这种使用WAL技术似乎并不能发挥最大性能(我的理解:基于SSD的WAL更多的只是起到队列一样削峰填谷的作用)。对于一些数据量不是特别大,但读写频繁的应用(比如点赞、积分),有没有更好的引擎推荐。展开
作者回复: 即使是SSD,顺序写也比随机写快些的。 不过确实没有机械盘那么明显。
共 3 条评论20 - Long2019-02-08老师新年好 :-) 刚好遇到一个问题。 本来准备更新到,一个查询是怎么运行的里面的,看到这篇更新文章,就写在这吧,希望老师帮忙解答。 关于这个系统memory引擎表:information_schema.tables 相关信息如下 (1)Verison: MySQL 5.6.26 (2)数据量table_schema = abc的有接近4W的表,整个实例有接近10W的表。(默认innodb引擎) (3)mysql.user和mysql.db的数据量都是100-200的行数,MyISAM引擎。 (4)默认事务隔离级别RC 在运行查询语句1的时候:select * from information_schema.tables where table_schema = 'abc'; 状态一直是check permission,opening tables,其他线程需要打开的表在opend tables里面被刷掉的,会显示在opening tables,可能需要小几秒后基本恢复正常。 但是如果在运行查询语句2:select count(1) from information_schema.tables where table_schema = 'abc'; 这个时候语句2本身在profiling看长期处于check permission状态,其他线程就会出现阻塞现象,大部分卡在了opening tables,小部分closing tables。我测试下了,当个表查询的时候check permission大概也就是0.0005s左右的时间,4W个表理论良好状态应该是几十秒的事情。 但是语句1可能需要5-10分钟,语句2需要5分钟。 3个问题,请老师抽空看下: (1)information_schema.tables的组成方式,是我每次查询的时候从数据字典以及data目录下的文件中实时去读的吗? (2)语句1和语句2在运行的时候的过程分别是怎样的,特别是语句2。 (3)语句2为什么会出现大量阻塞其他事务,其他事务都卡在opening tables的状态。 PS: 最后根据audit log分析来看,语句实际上是MySQL的一个客户端Toad发起的,当使用Toad的object explorer的界面来查询表,或者设置connection的时候指定的的default schema是大域的时候就会run这个语句:(table_schema改成了abc,其他都是原样) SELECT COUNT(1) FROM information_schema.tables WHERE table_schema = 'abc' AND table_type != 'VIEW'; 再次感谢!展开
作者回复: 1&2 查询information_schema.tables的时候,会把所有的表都访问到一次,这里不止是4w个表,而是这个实例上所有的表,也就是10万 3. 因为系统一般设置的table_definition_cache 都不会太大,你要打开10万张表,就只能轮流打开,然后轮流从table_definition_cache里面淘汰。这样就跟其他查询在table_definition_cache这个结构里出现了互相等待资源的情况。 嗯,这个其实就是我不建议用界面工具的原因之一 不好意思,你这个问题这么迟才回复你😆
17 - 往事随风,顺其自然2019-02-09为什么memory 引擎中数据按照数组单独存储,0索引对应的数据怎么放到数组的最后
作者回复: 这就是堆组织表的数据存放方式
共 3 条评论16 - skyoo2019-02-11重启前 my.cnf 添加 skip-slave-errors 忽略 内存表引起的主从异常导致复制失败
作者回复: 嗯,这个也是可以的。不过也会放过其他引擎表的主备不一致的报错哈
15 - Geek_da015d2020-11-25很重要的一点没说啊,内存表不支持事务。怪不得写demo的时候总锁不住共 3 条评论14
- llx2019-02-111、如果临时表读数据的次数很少(比如只读一次),是不是建临时表时不创建索引效果很更好? 2、engine=memory 如果遇到范围查找,在使用哈希索引时应该不会使用索引吧
作者回复: 1. 取决于对临时表的访问模式哦,如果是需要用到索引查找,还是要创建的。如果创建的临时表只是用于全表扫描,就可以不创建索引; 2. 是的,如果明确要用范围查找,就得创建b-tree索引
12 - 杜嘉嘉2019-02-10我的认识里,有一点不是很清楚。memory这个存储引擎,最大的特性应该是把数据存到内存。但是innodb也可以把数据存到内存,不但可以存到内存(innodb buffer size),还可以进行持久化。这样一对比,我感觉memory的优势更没有了。不知道我讲的对不对
作者回复: 是,如我们文中说的,不建议使用普通内存表了哈
10 - 晚风·和煦2020-01-16老师,内存表就是使用memory引擎创建的表吗?😂
作者回复: 对
7 - 陈扬鸿2019-03-06老师你好,今天生产上出碰到一个解决不了的问题,php的yii框架,使用show full processlist 查看 全是如下语句有100多条 SELECT kcu.constraint_name, kcu.column_name, kcu.referenced_table_name, kcu.referenced_column_name FROM information_schema.referential_constraints AS rc JOIN information_schema.key_column_usage AS kcu ON ( kcu.constraint_catalog = rc.constraint_catalog OR (kcu.constraint_catalog IS NULL AND rc.constraint_catalog IS NULL) ) AND kcu.constraint_schema = rc.constraint_schema AND kcu.constraint_name = rc.constraint_name WHERE rc.constraint_schema = database() AND kcu.table_schema = database() AND rc.table_name = 't1' AND kcu.table_name = 't1' 这个可以优化吗 这个库是数据字典的 现在数据库无法对外提供服务 请老师指教!展开
作者回复: 你看看能不能把短连接改成长连接 还有,这个语句应该是没用的,看看能不能通过配置框架参数,来避免执行这个语句
共 2 条评论6 - 夹心面包2019-02-11我们线上就有一个因为内存表导致的主从同步异常的例子,我的做法是先跳过这个表的同步,然后开发进行改造,取消这张表的作用
作者回复: 嗯嗯,联系开发改造是对的😆
5 - antz2021-06-18问句:在真实业务场景中真的有像文中动态创建临时表这么用的吗?怎么感觉这么反人类啊2
- 长杰2019-02-09内存表一般数据量不大,并且更新不频繁,可以写一个定时任务,定期检测内存表的数据,如果数据不空,就将它持久化到一个innodb同结构的表中,如果为空,就反向将数据写到内存表中,这些操作可设置为不写入binlog。
作者回复: 因为重启的时候已经执行了delete语句,所以再写入数据的动作也可以保留binlog哈
2 - Long2019-03-01追问更新1: 谢谢老师的答复,我看了下innodb_stats_on_metadata就是OFF,今天在5.7环境验证,发现竟然不是几百秒,而且几秒,不知道这个是代码的优化,还是参数不一致的原因,有几十个参数差异需要排查。 所以在不知道是因为参数变化导致,还是内部查询逻辑变化。如果是参数,担心有一天被人设置错,又回滚到不好的情况. 老师,我想入坑源码了…
作者回复: 这种情况最适合源码入坑😄 你有两个可以稳定复现的对比场景,而且单线程就能复现。 这两天我用电脑不方便,下周末来给出答案哈。 你可否把5.6/5.7这个对照试验组,包括实验过程和结果差异,再单独写一个问题😄
1 - Long2019-03-01追问:多谢老师回复,在上面回复中,为什么语句2会阻塞其他的线程把其他线程都卡在opening tables 和closing tables,而语句1不会. 猜测是不是语句2用了lock_open的方法? 老师有什么好的建议,我怎么能通过日志或者调试来看? 已经看了innodb status, processlist, profiling都看了,没发现异常 语句1: SELECT table_name, table_schema, data_length, index_length FROM information_schema.TABLES WHERE ENGINE in ('MyISAM','InnoDB') and table_schema <> 'information_schema'; 语句2:select count(1) from information_schema.tables where table_schema = 'abc';展开
作者回复: 你如果是innodb_stats_on_metadata设置为off的话,第二个语句是不用打开表的。
1 - 码小呆2023-01-28 来自广东有一个问题就是,备库,为什么还需要去同步主库呢,不应该都是主库去更新备库吗
- yangman2021-08-13老师你好,有个问题:为什么相同的数据,t1和t2的data_length会相差这么大? Name |Engine|Rows |Data_length| -----+------+-----+-----------+ t1 |MEMORY| 10| 126992| t2 |InnoDB| 10| 16384|
- bulingbuling2021-06-02老师: memory和innodb引擎的区别第3点:数据位置发生变化的时候,InnoDB 表只需要修改主键索引,而内存表需要修改所有索引。这句话没理解,数据位置发生变化的时候,memory修改所有索引的原理是什么
- Geek_66dfcd2020-11-13临时表是临时表,临时表存在磁盘上,内存表是内存表,内存表存在内存中,为什么这里说用户临时表是普通内存表的一个例外呢?共 1 条评论
- DavidJiang2020-11-06按照全表扫描原理,扫描的行数应该是总行数。但是如下实验发现并不相同。—todo list 另外,增加了list,原则上应该扫描前十行就可以了,为啥也是全表扫描 mysql> select count(*) from employees; +----------+ | count(*) | +----------+ | 300024 | +----------+ 1 row in set (0.09 sec) mysql> explain select * from employees ; +----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-------+ | 1 | SIMPLE | employees | NULL | ALL | NULL | NULL | NULL | NULL | 299202 | 100.00 | NULL | +----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-------+ 1 row in set, 1 warning (0.02 sec) mysql> explain select * from employees limit 10; +----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-------+ | 1 | SIMPLE | employees | NULL | ALL | NULL | NULL | NULL | NULL | 299202 | 100.00 | NULL | +----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-------+ 1 row in set, 1 warning (0.01 sec)展开共 1 条评论