简体   繁体   English

InnoDB 与 MyISAM 插入查询时间

[英]InnoDB vs. MyISAM insert query time

I have a large MySQL table (~10 Million Rows, 6.5G) Which i use for read & write.我有一个大型 MySQL 表(约 1000 万行,6.5G),用于读写。 It is MyISAM, and i get a lot of locks due to MyISAM's all table lock on writes.它是 MyISAM,由于 MyISAM 的所有表在写入时锁定,我得到了很多锁定。

I decided to try and move to InnoDB which is recommended for read/write tables, and it locks only specific rows on writes.我决定尝试迁移到推荐用于读/写表的 InnoDB,它只在写入时锁定特定行。

After converting, I tested insert statements, and it turns out it takes ~15 times more (from 0.1 sec to 1.5 sec) in the InnoDB table than in the MyISAM table.转换后,我测试了插入语句,结果发现 InnoDB 表中的时间比 MyISAM 表中的时间多约 15 倍(从 0.1 秒到 1.5 秒)。 Why is that?这是为什么?

I haven't configured anything for InnoDB yet, and plan to add partitions also, but this figure is still unexpected for me.我还没有为 InnoDB 配置任何东西,也计划添加分区,但是这个数字对我来说仍然是出乎意料的。 Of course the tables are the same, same indexes etc.当然,表是相同的,相同的索引等。

Additional info according to requests:根据要求提供的附加信息:

2 indexes. 2个指标。 primary is data_id of type Big INT, and non unique user_id of type varchar(255).主要是 Big INT 类型的 data_id 和 varchar(255) 类型的非唯一 user_id。

Inserts are of ~150 rows together that have the same user_id.插入大约有 150 行,它们具有相同的 user_id。

Size of indexes: 200 MB in MyISAM, 400MB in InnoDB索引大小:MyISAM 200 MB,InnoDB 400MB

A related answer suggests that setting the innodb_flush_log_at_trx_commit variable to 2 is likely to improve performance when the ratio of writes to reads is relatively high.一个相关的答案表明,当写入与读取的比率相对较高时,将innodb_flush_log_at_trx_commit变量设置为 2 可能会提高性能。 See the documentation for more.有关更多信息,请参阅文档

I think, InnoDB implements a true ACID, and does a lot of fsync() s to save the data.我认为,InnoDB 实现了真正的 ACID,并且做了很多fsync()来保存数据。 And MyISAM is not a true ACID and does less fsync()s.而且 MyISAM 不是真正的 ACID,并且 fsync() 的作用更少。

There are recomendations to kill fsync when you need to load huge data in当您需要加载大量数据时, 有一些建议可以杀死 fsync

If you want to load data into InnoDB quickly:
* use as large an InnoDB buffer cache as possible
* make the InnoDB log files as large as possible
* minimize the number of unique indexes on your tables
* disable all calls to fsync from InnoDB. You have to hack the code to
get this, or look at the Google patch. Of course, you only want to run
in this mode when loading the table.

And lists says : 并列出说

MyISAM always runs in the 'nosync' mode, that is, it never calls fsync() to flush the files to disk. MyISAM 始终以“nosync”模式运行,也就是说,它从不调用 fsync() 将文件刷新到磁盘。

InnoDB's nosync is useful in testing if some OS/computer is extremely slow in fsync(). InnoDB 的 nosync 在测试某些操作系统/计算机是否在 fsync() 中非常慢时很有用。 But it should not be used in a production system.但它不应该用于生产系统。

The same message says, that InnoDB sometimes uses another sync method:同样的消息说,InnoDB 有时使用另一种同步方法:

Then InnoDB uses fsync() to flush both the data and log files.然后 InnoDB 使用 fsync() 来刷新数据和日志文件。 If O_DSYNC is specified, InnoDB uses O_SYNC to open and flush the log files, but uses fsync() to flush the data files.如果指定了 O_DSYNC,InnoDB 使用 O_SYNC 打开和刷新日志文件,但使用 fsync() 刷新数据文件。 If O_DIRECT is specified (available on some Linux versions starting from MySQL-4.0.14), InnoDB uses O_DIRECT to open the data files, and uses fsync() to flush both the data and log files.如果指定了 O_DIRECT(在一些从 MySQL-4.0.14 开始的 Linux 版本上可用),InnoDB 使用 O_DIRECT 打开数据文件,并使用 fsync() 刷新数据和日志文件。 Note that InnoDB does not use fdatasync() or O_DSYNC because there have been problems with them on many Unix flavors.请注意,InnoDB 不使用 fdatasync() 或 O_DSYNC,因为它们在许多 Unix 版本上都存在问题。

Keep in mind the way InnoDB handles keys can cause trouble.请记住 InnoDB 处理键的方式可能会导致麻烦。 Since everything is stored on disk in the order of the primary key having a non-auto-increment primary key might cause much of the table to be moved on disk with any insert (I ran into this problem when I had a pivot table and used the combined ids as a primary key).由于所有内容都按照具有非自动增量主键的主键的顺序存储在磁盘上,因此可能会导致大部分表随任何插入移动到磁盘上(当我有一个数据透视表并使用组合的 id 作为主键)。 Moving data on disk is slow.在磁盘上移动数据很慢。

Also the index sizes can be much larger with InnoDB because each index also contains the primary key.此外,InnoDB 的索引大小可以更大,因为每个索引还包含主键。 Check to be sure you are not running into any memory limits.检查以确保您没有遇到任何内存限制。

First, your test is invalid , since the speed gain of row-level locking against table level locking comes when you have concurrency!首先,你的测试是无效的,因为当你有并发时,行级锁定相对于表级锁定的速度增益来了! With only 1 thread making inserts, you have 1 lock/unlock per insert in both cases, and inserts are not waiting the table-level lock to be released.只有 1 个线程插入插入,在这两种情况下每个插入都有 1 个锁定/解锁,并且插入不等待表级锁定被释放。

Seconds, as stated by JIStone, non-sequential primary key is performance killer for the inserts, when the table size is bigger then the buffer pool.几秒钟,正如 JIStone 所说,当表大小大于缓冲池时,非顺序主键是插入的性能杀手。

Third, the buffer pool size is one of the most important settings in InnoDB.第三,缓冲池大小是 InnoDB 中最重要的设置之一。 Make it as lare as possible (recommended setting is 80% ot the available RAM).使其尽可能小(推荐设置为可用 RAM 的 80%)。

Next, as stated by @wallyk, innodb_flush_log_at_trx_commit have crucial role for speed of I/O operations.接下来,正如@wallyk 所说,innodb_flush_log_at_trx_commit 对 I/O 操作的速度起着至关重要的作用。

Next, the innodb_log_file_size and innodb_buffer_file_size are important to.接下来, innodb_log_file_size 和 innodb_buffer_file_size 很重要。

Next, keep in mind, that since you have 2 unique indexes, before InnoDB can insert the row, it have to check the existence of the value in the indexes, and your indexes are large.接下来,请记住,由于您有 2 个唯一索引,在 InnoDB 插入行之前,它必须检查索引中的值是否存在,并且您的索引很大。

Without having details about the table and indexes, I cannnot give you more advices, but please keep in mind, that no storage engine is a panacea, and although often you can gain a lot of speed by simply changing storage engine, adding index, or tweaking one variable, in large-scale systems the things are more complex than this.没有表和索引的详细信息,我不能给你更多的建议,但请记住,没有存储引擎是灵丹妙药,虽然通常你可以通过简单地改变存储引擎,添加索引,或调整一个变量,在大型系统中,事情比这更复杂。 But, as I said, you should not compare the raw insert speed in isolated test, you have to make your test as close to the real application as possible.但是,正如我所说,您不应该比较孤立测试中的原始插入速度,您必须使您的测试尽可能接近实际应用程序。

update : one more tip In both MyISAM and InnoDB, multi-insert (insert into .... values(...),(...),(...)) is faster.更新:另外一个技巧 在 MyISAM 和 InnoDB 中,多插入(插入 .... values(...),(...),(...))更快。 Also, in InnoDB you can make your inserts in transaction, which disables updating non-unique indexes before transaction completes, and it's faster as well (but do not perform large transactions, as this actually will slow things down because of the isolation level used and the way row-versioning works).此外,在 InnoDB 中,您可以在事务中进行插入,这会在事务完成之前禁用更新非唯一索引,而且速度也更快(但不要执行大型事务,因为这实际上会因为使用的隔离级别而减慢速度和行版本控制的工作方式)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM