Friday, January 29, 2010

InnoDB Performance Tuning

InnoDB Performance Tuning

InnoDB is a transaction-safe, ACID compliant MySQL storage engine. It has commit, rollback, and crash recovery capabilities, and offers row level locking. The engine's overview page explains, “InnoDB has been designed for maximum performance when processing large data volumes. Its CPU efficiency is probably not matched by any other disk-based relational database engine.”

Insert Performance

  • Only flush logs once per second

    Tunable: innodb_flush_log_at_trx_commit

    By default, the InnoDB storage engine is ACID compliant, meaning that it flushes each transaction to the file system when it is committed. You can set the above tunable to 0 to disable this, telling InnoDB to flush to disk only once per second. Alternatively, you can set the above tunable to 2, letting the file system handle the flushing of data to the disk.

  • Increase the log buffer

    Tunable: innodb_log_buffer_size

    As the InnoDB storage engine flushes its buffer a minimum of once ever second, there's no reason to set this buffer very large unless you are inserting very large data into the table (such as large BLOB fields). For most systems doing lots of INSERTS, increasing this tunable to anywhere from 2M to 8M should be sufficient.

  • Increase the InnoDB log file size

    Tunable: innodb_log_file_size

    When data is added into an InnoDB table, it is first stored in an InnoDB log file. If you're inserting large quantities of data, it can greatly boost performance to increase the size of these log files. If you do a lot of inserts, you should boost your log file size to at least 25% the size of your buffer pool. For best performance, you may want to increase your total log file size up to the size of your buffer pool (up to a current limit of 4GB). However, note that allocating large InnoDB log files mean that recovery time is very slow. If MySQL crashes, InnoDB will have to parse the entire log files at startup time, a very time consuming process.

    Note: It's not enough to just edit my.cnf to change the size of your log files. Instead, you must do all of the following steps:

    1. Edit my.cnf, setting a new log file size.
    2. Gracefully shut down the MySQL server.
    3. Remove (or archive) the existing InnoDB log files
    4. Start the MySQL server, allowing it to create new log files.
    5. Verify that the new log files are the size you set in step #1.
  • Test alternative flush methods

    Tunable: innodb_flush_method

    By default, InnoDB uses the fsync() system call. On some systems it can be faster to flush using O_DSYNC. It is important to benchmark this change, as which flush method will perform best is dependent on your system.

  • Disable AUTOCOMMIT

    InnoDB treats all statements as transactions, adding overhead when inserting lots of data. If you need to INSERT lots of data, first call “SET AUTOCOMMIT = 0;”. Then, execute a group of INSERT statements followed by a manual “COMMIT;”. It is best to run some benchmarks to determine the optimal size for your transactions. If you make your transactions too big, they will become disk-bound, reducing INSERT performance. You can increase the supported size of your commits by increasing the size of your Buffer Pool.

  • Disable UNIQUE_CHECKS

    If you have UNIQUE constraints on any of your secondary keys, you can greatly boost insert performance into large tables by running “SET UNIQUE_CHECKS=0” before you INSERT the data, and then “SET UNIQUE_CHECKS=1” when you are done. However, be certain that you are not inserting any duplicate data before you do this.

  • Presort your data by the Primary Key

    InnoDB physically stores data sorted by the primary key. Thus, if you presort your data before you INSERT it into the database the InnoDB storage engine can handle it more efficiently. If you INSERT data in a random order, it can also cause your tables to become fragmented. If there's no way to INSERT data in order, you may want to consider making your primary key an auto_increment field.

General Performance Tips

  • Search with your Primary Key

    InnoDB offers optimal performance for searching by PRIMARY KEY compared to any other index. This is because data is stored on disk and in memory sorted by the primary key.

  • Keep your Primary Key short

    If your Primary Keys are long, this will result in very large, slow indexes. If your existing Primary Key is long, you may want to convert it to a Unique Key, then add a new auto_increment field as the primary key. If, however, you do your lookups using only the Primary Key, then leave it as is even if the Primary Key column is long.

  • Only create necessary indexes

    InnoDB stores an uncompressed copy of your Primary Key with each Secondary Key. Thus, if you have lots of indexes and you have a large Primary Key, your indexes are going to use a lot of disk space.

  • Optimizing SELECT COUNT(*)

    The design of the InnoDB storage engine prevents it from storing the actual row count of each table, thus it actually has to count rows to return SELECT COUNT(*). However, if you add a WHERE clause to the COUNT(*), InnoDB will offer the same performance as MyISAM. Alternatively, you can parse SHOW TABLE STATUS LIKE “NAME” to get quick access to an estimate of the number of rows in table NAME. (For static tables, this will be accurate. For quickly changing tables, it will just be close.)

  • Don't empty a table with DELETE FROM or TRUNCATE

    Emptying a large table using DELETE FROM or TRUNCATE is slow on InnoDB. This is because for both operations InnoDB has to process each row of the table, and due to its transactional design it first writes each delete action to the transaction log then applies it to the actual table. For better performance if not limited by foreign keys, use DROP TABLE followed by CREATE TABLE to empty a large table.



InnoDB Performance Worksheet - Drupal Performance and Scalability Checklist

InnoDB Performance Worksheet - Drupal Performance and Scalability Checklist

Source: Drupal Performance Agency # Pages: 4

Last Modified: 10:49 PM Jan 12, 2008 License: Creative Commons AttributionShareAlike2.0

Description: InnoDB is a transactionsafe, ACID compliant MySQL storage engine. It has commit, rollback, and crash recovery capabilities, and offers row level locking. The engine's overview page explains, “InnoDB has been designed for maximum performance when processing large data volumes. Its CPU efficiency is probably not matched by any other diskbased relational database engine.”

This checklist was designed by the Drupal Performance Agency. For more information, email perf@tag1consulting.com.

INSERT

I. Increase the log buffer

Tunable: innodb_log_buffer_size

As the InnoDB storage engine flushes its buffer a minimum of once ever second, there's no reason to set this buffer very large unless you are inserting very large data into the table (such as large BLOB fields). For most systems doing lots of INSERTS, increasing this tunable to anywhere from 2M to 8M should be sufficient.

II. Increase the InnoDB log file size

Tunable: innodb_log_file_size

When data is added into an InnoDB table, it is first stored in an InnoDB log file. If you're inserting large quantities of data, it can greatly boost performance to increase the size of these log files. If you do a lot of inserts, you should boost your log file size to at least 25% the size of your buffer pool. For best performance, you may want to increase your total log file size up to the size of your buffer pool (up to a current limit of 4GB). However, note that allocating large InnoDB log files mean that recovery time is very slow. If MySQL crashes, InnoDB will have to parse the entire log files at startup time, a very time consuming process.

Note: It's not enough to just edit my.cnf to change the size of your log files. Instead, you must do all of the following steps:

1. Edit my.cnf, setting a new log file size.

2. Gracefully shut down the MySQL server.

3. Remove (or archive) the existing InnoDB log files

4. Start the MySQL server, allowing it to create new log files.

5. Verify that the new log files are the size you set in step #1.

III. Only flush logs once per second

Tunable: innodb_flush_logs_at_trx_commit

By default, the InnoDB storage engine is ACID compliant, meaning that it flushes each transaction to the file system when it is committed. You can set the above tunable to 0 to disable this, telling InnoDB to flush to disk only once per second. Alternatively, you can set the above tunable to 2, letting the file system handle the flushing of data to the disk.

IV. Test alternative flush methods

Tunable: innodb_flush_method

By default, InnoDB uses the fsync() system call. On some systems it can be faster to flush using O_DSYNC. It is important to benchmark this change, as which flush method will perform best is dependent on your system.

V. Disable AUTOCOMMIT
InnoDB treats all statements as transactions, adding overhead when inserting lots of data. If you need to INSERT lots of data, first call “SET AUTOCOMMIT = 0;”. Then, execute a group of INSERT statements followed by a manual “COMMIT;”. It is best to run some benchmarks to determine the optimal size for your transactions. If you make your transactions too big, they will become diskbound, reducing INSERT performance.

You can increase the supported size of your commits by increasing the size of your Buffer Pool.

VI. Disable UNIQUE_CHECKS
If you have UNIQUE constraints on any of your secondary keys, you can greatly boost insert performance into large tables by running “SET UNIQUE_CHECKS=0” before you INSERT the data, and then “SET UNIQUE_CHECKS=1” when you are done. However, be certain that you are not inserting any duplicate data before you do this.

VII. Presort your data by the Primary Key
InnoDB physically stores data sorted by the primary key. Thus, if you presort your data before you INSERT it into the database the InnoDB storage engine can handle it more efficiently. If you INSERT data in a random order, it can also cause your tables to become fragmented. If there's no way to INSERT data in order, you may want to consider making your primary key an auto_increment field.

General

I. Search with your Primary Key
InnoDB offers optimal performance for searching by PRIMARY KEY compared to any other index. This is because data is stored on disk and in memory sorted by the primary key.

II. Keep your Primary Key short
If your Primary Keys are long, this will result in very large, slow indexes. If your existing Primary Key is long, you may want to convert it to a Unique Key, then add a new auto_increment field as the primary key. If, however, you do your lookups using only the Primary Key, then leave it as is even if the Primary Key column is long.

III. Only create necessary indexes
InnoDB stores an uncompressed copy of your Primary Key with each Secondary Key. Thus, if you have lots of indexes and you have a large Primary Key, your indexes are going to use a lot of disk space.

IV. Optimizing SELECT COUNT(*)
The design of the InnoDB storage engine prevents it from storing the actual row count of each table, thus it actually has to count rows to return SELECT COUNT(*). However, if you add a WHERE clause to the COUNT(*), InnoDB will offer the same performance as MyISAM. Alternatively, you can parse SHOW TABLE STATUS FROM db_name LIKE 'table_name%' \G to get quick access to an estimate of the number of rows in table NAME. (For static tables, this will be accurate. For quickly changing tables, it will just be close.)

V. Don't empty a table with DELETE FROM or TRUNCATE
Emptying a large table using DELETE FROM or TRUNCATE is slow on InnoDB. This is because for both operations InnoDB has to process each row of the table, and due to its transactional design it first writes each delete action to the transaction log then applies it to the actual table. For better performance if not limited by foreign keys, use DROP


TABLE followed by CREATE TABLE to empty a large table.

Reference:
http://tag1consulting.com/files/InnoDB_0.pdf
http://tag1consulting.com/InnoDB_Performance_Tuning

promiscuous mode enabled

Jan 28 12:04:53 bsd-test kernel: em0: promiscuous mode enabled
Jan 28 12:04:53 bsd-test kernel: em0: promiscuous mode disabled

# ifconfig -a
em0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> metric 0 mtu 1500

to answer the rest of your question:

promiscious mode means the interface listens to all traffic that comes across it; various applications (particularly sniffers,) place an interface in promiscous mode in order to sniff network info (notably tcpdump and any other apps that use tcpdump's functions, like ethereal).

Here are some suggestions from Elements of Programming Style

Here are some suggestions from Elements of Programming Style:

* Make sure all variables are initialized before use.
* Don't stop at one bug (there are always more).
* Initialize constants in the DATA DIVISION; initialize variables
* with executable code.
* Watch for off-by-one errors.
* Test programs at their boundary values.
* Program defensively.

Wednesday, January 27, 2010

MySQL Engines: InnoDB vs. MyISAM – A Comparison of Pros and Cons

The 2 major types of table storage engines for MySQL databases are InnoDB and MyISAM. To summarize the differences of features and performance,
  1. InnoDB is newer while MyISAM is older.
  2. InnoDB is more complex while MyISAM is simpler.
  3. InnoDB is more strict in data integrity while MyISAM is loose.
  4. InnoDB implements row-level lock for inserting and updating while MyISAM implements table-level lock.
  5. InnoDB has transactions while MyISAM does not.
  6. InnoDB has foreign keys and relationship contraints while MyISAM does not.
  7. InnoDB has better crash recovery while MyISAM is poor at recovering data integrity at system crashes.
  8. MyISAM has full-text search index while InnoDB has not.
In light of these differences, InnoDB and MyISAM have their unique advantages and disadvantages against each other. They each are more suitable in some scenarios than the other.

Advantages of InnoDB

  1. InnoDB should be used where data integrity comes a priority because it inherently takes care of them by the help of relationship constraints and transactions.
  2. Faster in write-intensive (inserts, updates) tables because it utilizes row-level locking and only hold up changes to the same row that’s being inserted or updated.

Disadvantages of InnoDB

  1. Because InnoDB has to take care of the different relationships between tables, database administrator and scheme creators have to take more time in designing the data models which are more complex than those of MyISAM.
  2. Consumes more system resources such as RAM. As a matter of fact, it is recommended by many that InnoDB engine be turned off if there’s no substantial need for it after installation of MySQL.
  3. No full-text indexing.

Advantages of MyISAM

  1. Simpler to design and create, thus better for beginners. No worries about the foreign relationships between tables.
  2. Faster than InnoDB on the whole as a result of the simpler structure thus much less costs of server resources.
  3. Full-text indexing.
  4. Especially good for read-intensive (select) tables.

Disadvantages of MyISAM

  1. No data integrity (e.g. relationship constraints) check, which then comes a responsibility and overhead of the database administrators and application developers.
  2. Doesn’t support transactions which is essential in critical data applications such as that of banking.
  3. Slower than InnoDB for tables that are frequently being inserted to or updated, because the entire table is locked for any insert or update.
The comparison is pretty straightforward. InnoDB is more suitable for data critical situations that require frequent inserts and updates. MyISAM, on the other hand, performs better with applications that don’t quite depend on the data integrity and mostly just select and display the data.

Wednesday, January 20, 2010

CRLF line terminators makes shell script failed to run.

CRLF line terminators makes shell script failed to run.

shell script does not work properly.

I have a script like this:

# cat test
#!/bin/sh
cat `find /usr/local/www/backup/scripts/crontab/coredata/logs -type f | sort | tail -n 1`

# file test
test: ASCII English text, with CRLF line terminators

That cause the script failed to run.

Change it to unix line feed to solve the problem

修正 Apache Worker MPM 與 APC 設定

最近觀察主機,常常會難連線,可是一切卻又運作中。觀察圖表,發現是記憶體暴增,然後就吃到 SWAP 去,結果就是狂 hang 住。應該是常常有 spam 公司來幫忙測試主機,所以 request 太多,就暴了!

現在小小的主機、慢慢的 CPU、少少的 RAM 實在沒辦法像 Pixnet 這樣借人家測主機XD。所以只好修正一下參數,目前測試下來,這樣的設定是最 OK 的,雖然 Request 多的時候還是會連線稍慢一點點,不過至少 Performance好很多。

目前主機配置是:PIII-800、384Ram,就是這麼遜,所以各位 Spam 大哥不要來亂了!

Worker MPM 配置如下:


StartServers 1
ServerLimit 3
MaxClients 100
MinSpareThreads 25
MaxSpareThreads 50
ThreadLimit 50
ThreadsPerChild 50
MaxRequestsPerChild 10000

分享一下參數設定的心得好了:

「StartServers」就是剛啟動時要先生出來的 httpd 程序數量,而「ServerLimit」定義了最大程序數量,每個程序裡面會包含「ThreadsPerChild」個 Thread(每個 Thread都可以應對一個 Request,不需要傳統那樣一個 Request 就需要一個程序。而當不夠的時候,他會自動增加 Thread 或 Child 來處理),「MinSpareThreads」和「MaxSpareThreads」定義了最少和最多的空閒 Thread 數量。接著,這邊用「ThreadLimit」來限制了每個 Child 的最大 Thread 數量。而「ThreadPerChild」和「ServerLimit」的乘績決定了「MaxClients」的上限,也就是能夠承受的最大 Request 數量。最後是「MaxRequestsPerChild」,決定了 Child 接受了幾個 Request 之後就要關閉,等待如果需要才重新產生一個程序。預設是零,也就是不結束,不過我比較喜歡重新產生,可以避免安全問題,更重要的是不需要那麼多程序時不會佔用著資源。

調整的時候,可以搭配 ab 壓力測試:

ab -c 同時連線數量 -n 每個連線的Request數量

這個設定可以讓我的主機 Lifetype 部分稱到 ab -c 50 -n500 才 timeout 結束,但是 SWAP 還在 50M 以下。如果是靜態網頁、galler2、 其他 php 等等,更可以撐到 ab -c 100 -n 1000 以上沒問題。接著會觀察看看,希望不會再 hang 死。



另外,也調整了一下 apc 的設定,之前的 ttl 實在太可怕,迴響、文章發表更新,都要等很久,目前用了一陣子很滿意的設定是:

[APC]
apc.stat=0
apc.enabled=1
apc.shm_segments=1
apc.shm_size=128
apc.ttl=300
apc.user_ttl=300
apc.num_files_hint=1024
apc.mmap_file_mask=/tmp/apc.XXXXXX
apc.enable_cli=1

ttl 設定成 300 second,這樣快取命中率還是高達 96%,快取大約是 50M 上下,快取表現、更新速度也都符合需要。

參考看看。