MySQL poor performance in Centos 7

给你一囗甜甜゛ 提交于 2019-12-25 08:35:33

问题


I run a very simple MySQL database construct. I only have like id, TimeStamp and OP_fs155e columns which I consider is extremely basic setup.

MariaDB [gadbdfm]> desc optical_power;
+-----------+------------------+------+-----+----------------------+-----------------------------+
| Field     | Type             | Null | Key | Default              | Extra                       |
+-----------+------------------+------+-----+----------------------+-----------------------------+
| id_record | int(10) unsigned | NO   | PRI | NULL                 | auto_increment              |
| TimeStamp | timestamp(6)     | NO   |     | CURRENT_TIMESTAMP(6) | on update CURRENT_TIMESTAMP |
| OP_fs155e | varchar(30)      | YES  | MUL | NULL                 |                             |
| data1     | varchar(30)      | YES  |     | NULL                 |                             |
| data2     | varchar(30)      | YES  |     | NULL                 |                             |
| data3     | varchar(30)      | YES  |     | NULL                 |                             |
| data4     | varchar(30)      | YES  |     | NULL                 |                             |
| data5     | varchar(30)      | YES  |     | NULL                 |                             |
+-----------+------------------+------+-----+----------------------+-----------------------------+
8 rows in set (0.00 sec)

However, I start noticing that my selects are terribly slow first at Raspberry Pi 3 (as master) and Centos7 (as slave - 8GB muscle server). Here is my select everything at slave server which took several minutes. I thought that the problem is that Raspberry Pi 3 is too slow but when I found out that it is the same at a real server slave, there is definitively something wrong with it.

MariaDB [gadbdfm]> select TimeStamp,OP_fs155e from optical_power;

| 2017-01-01 17:41:03.697000 | -24       |
| 2017-01-01 17:42:03.666000 | -24       |
| 2017-01-01 17:43:03.701000 | -24       |
| 2017-01-01 17:44:03.675000 | -24       |
| 2017-01-01 17:45:03.676000 | -24       |
| 2017-01-01 17:46:03.692000 | -24       |
| 2017-01-01 17:47:03.686000 | -24       |
| 2017-01-01 17:48:03.539000 | -24       |
| 2017-01-01 17:49:03.581000 | -24       |
+----------------------------+-----------+
23044062 rows in set (37.24 sec)

Master my.cnf

pi@rpi3jantoth - /opt/FlightStrata155E cat /etc/mysql/mysql.conf.d/mysqld.cnf | grep -v "#" | grep -v "^$"
[mysqld_safe]
socket      = /var/run/mysqld/mysqld.sock
nice        = 0
[mysqld]
user        = mysql
pid-file    = /var/run/mysqld/mysqld.pid
socket      = /var/run/mysqld/mysqld.sock
port        = 3306
basedir     = /usr
datadir     = /var/lib/mysql
tmpdir      = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking
bind-address        = 0.0.0.0
key_buffer_size     = 16M
max_allowed_packet  = 16M
thread_stack        = 192K
thread_cache_size       = 8
myisam-recover         = BACKUP
query_cache_limit   = 1M
query_cache_size        = 16M
log_error = /var/log/mysql/error.log
server-id       = 1
log_bin         = /var/log/mysql/mysql-bin.log
expire_logs_days    = 10
max_binlog_size   = 100M
relay-log = /var/lib/mysql/mysql-relay-bin
relay-log-index = /var/lib/mysql/mysql-relay-bin.index
log-error = /var/lib/mysql/mysql.err

Slave my.cnf:

[root@fiber ~]# cat /etc/my.cnf | grep -v "#" | grep -v "^$"
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0
server-id = 2
[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid
!includedir /etc/my.cnf.d

I know that I have zero optimization in my scheme.

One more example:

This select on Raspberry Pi 3 takes like 7 minutes

mysql> select TimeStamp, OP_fs155e from optical_power ORDER BY TimeStamp desc limit 15;

回答1:


The Raspberry Pi uses an SD card for storage, and therefore it's understandable that I/O performance is going to be much worse than a real server disk system.

Your first query that takes 37.24 seconds to return 23 million rows. That's quite a bit of I/O. I'd estimate you could fit about 500 rows per 16KB page (assuming your data columns are about 3 bytes each on average), so you'd need to read over 46,000 pages to read 23 million rows, which comes out to 755MB.

I bet that's more or less the data_length of your table, which you can check:

SHOW TABLE STATUS LIKE 'optical_power'\G

But the I/O rate for random reads on an SD card is between 2.28MB/sec and 8.10MB/sec, so it would take between 93 and 331 seconds to read 755MB from the SD card. That's just math.

Perhaps some data pages were already cached in MySQL's buffer pool, or InnoDB was able to do some read-ahead optimizations to help here.

Your second query is not optimized well. It has to use a filesort because there's no index on your TimeStamp column. The filesort might use temporary storage space, which incurs write I/O. Writes are much slower than reads on an SD card. So it's not surprising at all that it takes 7 minutes to do your ORDER BY TimeStamp LIMIT 15 query.

Apparently the brand of SD card makes a big difference. See http://www.jeffgeerling.com/blogs/jeff-geerling/raspberry-pi-microsd-card for some some comparisons.

But even if you get an SD card that's faster, you're still causing wear and tear on it by using I/O inefficiently. It'll be better to avoid I/O.

  • Create an index on your TimeStamp column, so the ORDER BY TimeStamp can use it instead of doing a filesort. Indexing is very important for optimizing queries. See my presentation How to Design Indexes, Really.
  • Many Raspberry Pi users store MySQL data in the MyISAM storage engine. MyISAM uses only buffered I/O, and has no crash-safety features. This should help improve I/O performance and decrease wear and tear on your SD card. Indexes and replication work just fine with MyISAM tables. MyISAM also tends to store data in less space than InnoDB.
  • Make sure you set sync_binlog=0 to allow the replication log to use async I/O as well.

If you must use InnoDB, tune it for maximum caching and minimum durability:

  • Increase the innodb_buffer_pool_size as much as you can spare. But don't make it so large that other processes don't have enough memory. Count on the buffer pool using another 10%, so if you set it to 512M, it'll really take 563M.
  • Avoid synchronous I/O and use buffered I/O wherever possible. See https://dev.mysql.com/doc/refman/5.5/en/optimizing-innodb-diskio.html

    innodb_flush_log_at_trx_commit=2
    innodb_flush_method=O_DSYNC
    innodb_doublewrite=0
    

Re your comment:

I am using 16GB USB Toshiba stick as the storage instead od SD card, because I has so much trouble with SD cards

A USB flash drive (stick) is not much different in performance than an SD card. Both devices are optimized for sequential read/write, not random read/write. They suck terribly as filesystems, or for database work.

The bottom line is if you need the performance of a real server, with data at a scale that belongs on a server, then don't use a Raspberry Pi.

I would expect a Raspberry Pi solution for data collection to not store any data on the Pi, but instead post the data immediately to a server on your network. A good solution would be to run a message queue server, collecting events posted by your various Pi devices. Then write a script to consumes the data from the message queue and post it to the database in batches.




回答2:


Well, regarding to your first suggestion:

Database changed
mysql> SHOW TABLE STATUS LIKE 'optical_power'\G
*************************** 1. row ***************************
           Name: optical_power
         Engine: InnoDB
        Version: 10
     Row_format: Compact
           Rows: 22030014
 Avg_row_length: 38
    Data_length: 843055104
Max_data_length: 0
   Index_length: 0
      Data_free: 7340032
 Auto_increment: 34973978
    Create_time: 2016-12-30 16:10:49
    Update_time: NULL
     Check_time: NULL
      Collation: latin1_swedish_ci
       Checksum: NULL
 Create_options: 
        Comment: 
1 row in set (0.00 sec)

I am using 16GB USB Toshiba stick as the storage instead od SD card, because I has so much trouble with SD cards.For instance, I use all of raspberry pi3 USB ports because there is a need to collect data from multiple sensors. I am trying

ALTER TABLE optical_power ADD INDEX(TimeStamp,OP_fs155e);

I highly appreciate your answer I will try to play with it.

Thanks so much

So it is just simple timestamp and value (OP_fs155e) table.

code mysql> select TimeStamp, OP_fs155e from optical_power ORDER BY TimeStamp desc limit 15;
+----------------------------+-----------+
| TimeStamp                  | OP_fs155e |
+----------------------------+-----------+
| 2017-01-01 17:49:03.581000 | -24       |
| 2017-01-01 17:48:03.539000 | -24       |
| 2017-01-01 17:47:03.686000 | -24       |
| 2017-01-01 17:46:03.692000 | -24       |
| 2017-01-01 17:45:03.676000 | -24       |
| 2017-01-01 17:44:03.675000 | -24       |
| 2017-01-01 17:43:03.701000 | -24       |
| 2017-01-01 17:42:03.666000 | -24       |
| 2017-01-01 17:41:03.697000 | -24       |
| 2017-01-01 17:40:03.688000 | -24       |
| 2017-01-01 17:39:03.574000 | -24       |
| 2017-01-01 17:38:03.596000 | -24       |
| 2017-01-01 17:37:03.545000 | -24       |
| 2017-01-01 17:36:03.667000 | -24       |
| 2017-01-01 17:35:03.544000 | -24       |
+----------------------------+-----------+
15 rows in set (2 min 41.32 sec)



回答3:


Hello @Bill Karwin and @Bernd Buffen! I highly appreciate your advice! I added like this index as show and explained in the presentation here:

mysql> ALTER TABLE optical_power ADD INDEX(TimeStamp,OP_fs155e);

and the result is 3.24 seconds compared to 2 minutes ot 7 minutes sometimes: AMAZING!!!

   mysql> use gadbdfm;
Database changed
mysql> select TimeStamp, OP_fs155e from optical_power ORDER BY TimeStamp desc limit 15;
+----------------------------+-----------+
| TimeStamp                  | OP_fs155e |
+----------------------------+-----------+
| 2017-01-01 17:49:03.581000 | -24       |
| 2017-01-01 17:48:03.539000 | -24       |
| 2017-01-01 17:47:03.686000 | -24       |
| 2017-01-01 17:46:03.692000 | -24       |
| 2017-01-01 17:45:03.676000 | -24       |
| 2017-01-01 17:44:03.675000 | -24       |
| 2017-01-01 17:43:03.701000 | -24       |
| 2017-01-01 17:42:03.666000 | -24       |
| 2017-01-01 17:41:03.697000 | -24       |
| 2017-01-01 17:40:03.688000 | -24       |
| 2017-01-01 17:39:03.574000 | -24       |
| 2017-01-01 17:38:03.596000 | -24       |
| 2017-01-01 17:37:03.545000 | -24       |
| 2017-01-01 17:36:03.667000 | -24       |
| 2017-01-01 17:35:03.544000 | -24       |
+----------------------------+-----------+
15 rows in set (3.24 sec)


来源:https://stackoverflow.com/questions/41418232/mysql-poor-performance-in-centos-7

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!