MySQL | MySQL 常见优化方案

MySQL 常见优化方案



1 优化数据库结构

1.1 优化表的数据类型

MySQL 支持的数据类型非常多,选择正确的数据类型对获得高性能至关重要

数值

类型大小(byte)有符号无符号用途
TINYINT1[-128, 127][0, 255]整数
SMALLINT2[-32768, 32767][0, 65535]整数
MEDIUMINT3[-8388608, 8388607](0,16 777 215)整数
INT或INTEGER4(-2147483648, 2147483647)(0,4294967295)整数
BIGINT8(-9,223,372,036,854,775,808,9 223 372 036 854 775 807)(0,18 446 744 073 709 551 615)整数
FLOAT4(-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38)0,(1.175 494 351 E-38,3.402 823 466 E+38)单精度 浮点数值
DOUBLE8(-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308)0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308)双精度浮点数值
DECIMAL对 DECIMAL(M,D) ,如果M>D,为M+2否则为D+2依赖于M和D的值依赖于M和D的值指定精度小数

时间

类型大小( byte)范围用途
DATE31000-01-01/9999-12-31YYYY-MM-DD 日期值
TIME3‘-838:59:59’/‘838:59:59’HH:MM:SS 时间值或持续时间
YEAR11901/2155 YYYY 年份值
DATETIME81000-01-01 00:00:00/9999-12-31 23:59:59 YYYY-MM-DD HH:MM:SS混合日期和时间值
TIMESTAMP41970-01-01 00:00:00/2038 结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07YYYYMMDD HHMMSS 混合日期和时间值,时间戳

字符

类型大小(byte)用途
CHAR0-255定长字符串
VARCHAR0-65535变长字符串
TINYBLOB0-255不超过 255 个字符的二进制字符串
TINYTEXT0-255短文本字符串
BLOB0-65 535二进制形式的长文本数据
TEXT0-65 535长文本数据
MEDIUMBLOB0-16 777 215二进制形式的中等长度文本数据
MEDIUMTEXT0-16 777 215中等长度文本数据
LONGBLOB0-4 294 967 295二进制形式的极大文本数据
LONGTEXT0-4 294 967 295极大文本数据

1.1.1 选择优化的数据类型

下面介绍几个简单的原则:

1. 更小的通常更好

一般情况下,应该尽可能的使用可以正确存储数据的最小的数据类型。小的数据类型占用更小的磁盘,内存和 CPU 缓存,并且处理时的 CPU 周期也更小

2. 简单就好

简单的数据类型的操作通常需要更少的 CPU 周期。例如,整型比字符操作代价更低

3. 尽量避免 NULL

1.1.2 整数类型

数字包括整数和实数。存储整数可以使用: TINYINT,SMALLINT MEDIUMINT,INT,BIGINT. 分别使用 8,16,24,32,64位存储空间。

整数类型可选UNSIGNED,表示不允许负值,这可以使正数的上限提高一倍。

有符号和无符号的性能是一样的,因此可以根据实际情况选择合适的类型。

MySQL 可以为整数类型指定宽度,例如 INT(11),INT(1), 对于大多数应用没有意义,因为MySQL不会限制值的合法范围,这只对一些交互工具用来显示使用。 INT(1)INT(11) 是相同的。

1.1.3 实数类型

实数是带有小数部分的数字。实数类型既可以存储小数也可以存储比BIGINT大的整数。

MySQL 既支持精确类型,也支持不精确类型

FLOATDOUBLE 支持标准的浮点运算进行近似计算

DECIMAL 支持精确的存储小数,

表需要使用何种数据类型,是需要根据应用来判断的。虽然应用设计的时候需要考虑字段的长度留有一定的冗余,但是不推荐让很多字段都留有大量的冗余,这样即浪费存储也浪费内存。

1.1.4 时间类型

需要根据时间范围选取合适的时间,这里注意下 TIMESTAMP 马上超过范围了

在表设计的时候,可以根据实际业务需要尽可能的使用可以正确存储数据的最小的数据类型。

1.1.5 分析已有数据

在线上业务已经稳定运行的时候,我们可以使用 PROCEDURE ANALYSE() 对当前已有应用的表类型的判断,该函数可以对数据表中的列的数据类型提出优化建议,可以根据应用的实际情况酌情考虑是否实施优化。

SELECT * FROM table_name PROCEDURE ANALYSE();  
SELECT * FROM tbl_name PROCEDURE ANALYSE(16,256)

输出的每一列信息都会对数据表中的列的数据类型提出优化建议。第二个例子告诉
PROCEDURE ANALYSE()不要为那些包含的值多于 16 个或者 256 字节的 ENUM 类型提出建议。如果没有这样的限制,输出信息可能很长;ENUM 定义通常很难阅读。

1.2 拆分表,提供访问效率

1.纵向拆分:

纵向拆分是只按照应用访问的频度,将表中经常访问的字段和不经常访问的字段拆分成两个表,经常访问的字段尽量是定长的,这样可以有效的提高表的查询和更新的效率。

2.横向拆分:

横向拆分是指按照应用的情况,有目的的将数据横向拆分成几个表或者通过分区分到多个分区中,这样可以有效的避免 Myisam 表的读取和更新导致的锁问题。

1.3 逆范式

数据库的规范化设计强调数据的独立性,数据应该尽可能少地冗余,因为存在过多的冗余数据,这就意味着要占用了更多的物理空间,同时也对数据的维护和一致性检查带来了问题。
但是对于查询操作很多的应用,一次查询可能需要访问多表进行,如果通过冗余纪录在相同表中,更新的代价增加不多,但是查询操作效率可以有明显提高,这种情况就可以考虑通过冗余数据来提高效率。

1.4 使用冗余统计表

使用create temporary table 语法,它是基于session 的表,表的数据保存在内存里面,当session 断掉后,表自然消除。
对于大表的统计分析,如果统计的数据量不大,利用insert。。。 select 将数据移到临时表中比直接在大表上做统计要效率更高。

1.5 选择更合适的表类型

  1. 如果应用出现比较严重的锁冲突,请考虑是否更改存储引擎到 innodb,行锁机制可以有效的减少锁冲突的出现。
  2. 如果应用查询操作很多,且对事务完整性要求不严格,则可以考虑使用Myisam

2. 定位慢SQL

3. 通过 EXPLAIN 分析执行计划

我们可以通过 explain 或者 desc 来获取 MySQL 的执行计划。

我们可以通过explain 或者desc 获取MySQL 如何执行 SELECT 语句的信息,包括select 语句执行过程表如何连接和连接的次序。
explain 可以知道什么时候必须为表加入索引以得到一个使用索引来寻找记录的更快的SELECT。

  • select_type: select 类型
  • table: 输出结果集的表
  • type: 表示表的连接类型
    • system: 当表中仅有一行时
    • ref: 使用索引进行表连接时type的值为ref
    • eq_ref: 连接没有使用索引时
    • ALL: 连接没有使用索引时
  • possible_keys: 表示查询时,可以使用的索引列.
  • key: 表示使用的索引
  • key_len: 索引长度
  • rows: 扫描范围
  • filtered
  • Extra: 执行情况的说明和描述

当表中仅有一行是type的值为system是最佳的连接类型; 当select操作中使用索引进行表连接时type的值为ref;
当select的表连接没有使用索引时,经常会看到type的值为ALL,表示对该表进行了全表扫描,这时需要考虑通过创建索引来提高表连接的效率。

4. 索引

下列情况下,MySQL 不会使用已有的索引:

  1. 如果 mysql 估计使用索引比全表扫描更慢,则不使用索引。例如:如果 age 均匀分布在 1 和 100 之间,下列查询中使用索引就不是很好:
    SELECT * FROM table_name where age > 1 and age < 90
  2. 如果使用 hash 索引且 where 条件中不用=索引列,其他> 、<、 >=、 <=均不使用索引;
  3. 如果不是索引列的第一部分;
  4. 如果 like 是以%开始;
  5. 对 where 后边条件为字符串的一定要加引号,字符串如果为数字 mysql 会自动转为字符串,但是不使用索引。

5. 其他优化措施

  1. 使用持久的连接数据库以避免连接开销。
  2. 经常检查所有查询确实使用了必要的索引。
  3. 避免在频繁更新的表上执行复杂的 SELECT 查询,以避免与锁定表有关的由于读、写冲突发生的问题。
  4. 对于没有删除的行操作的 MyISAM 表,插入操作和查询操作可以并行进行,因为没有删除操作的表查询期间不会阻塞插入操作.对于确实需要执行删除操作的表,尽量在空闲时间进行批量删除操作,避免阻塞其他操作。
  5. 充分利用列有默认值的事实。只有当插入的值不同于默认值时,才明确地插入值。这减少 MySQL 需要做的语法分析从而提高插入速度。
  6. 对经常访问的可以重构的数据使用内存表,可以显著提高访问的效率。
  7. 通过复制可以提高某些操作的性能。可以在复制服务器中分布客户的检索以均分负载。为了防止备份期间对应用的影响,可以在复制服务器上执行备份操作。
    表的字段尽量不使用自增长变量,在高并发情况下该字段的自增可能对效率有比较大的影响,推荐通过应用来实现字段的自增长。

参考

  1. 高性能 MySQL
  2. https://dev.mysql.com/doc/refman/5.7/en/

附录

show status 相关

Variable_nameValue
Aborted_clients0
Aborted_connects0
Binlog_cache_disk_use0
Binlog_cache_use0
Binlog_stmt_cache_disk_use0
Binlog_stmt_cache_use0
Bytes_received185
Bytes_sent645
Com_admin_commands0
Com_assign_to_keycache0
Com_alter_db0
Com_alter_db_upgrade0
Com_alter_event0
Com_alter_function0
Com_alter_instance0
Com_alter_procedure0
Com_alter_server0
Com_alter_table0
Com_alter_tablespace0
Com_alter_user0
Com_analyze0
Com_begin0
Com_binlog0
Com_call_procedure0
Com_change_db0
Com_change_master0
Com_change_repl_filter0
Com_check0
Com_checksum0
Com_commit0
Com_create_db0
Com_create_event0
Com_create_function0
Com_create_index0
Com_create_procedure0
Com_create_server0
Com_create_table0
Com_create_trigger0
Com_create_udf0
Com_create_user0
Com_create_view0
Com_dealloc_sql0
Com_delete0
Com_delete_multi0
Com_do0
Com_drop_db0
Com_drop_event0
Com_drop_function0
Com_drop_index0
Com_drop_procedure0
Com_drop_server0
Com_drop_table0
Com_drop_trigger0
Com_drop_user0
Com_drop_view0
Com_empty_query0
Com_execute_sql0
Com_explain_other0
Com_flush0
Com_get_diagnostics0
Com_grant0
Com_ha_close0
Com_ha_open0
Com_ha_read0
Com_help0
Com_insert0
Com_insert_select0
Com_install_plugin0
Com_kill0
Com_load0
Com_lock_tables0
Com_optimize0
Com_preload_keys0
Com_prepare_sql0
Com_purge0
Com_purge_before_date0
Com_release_savepoint0
Com_rename_table0
Com_rename_user0
Com_repair0
Com_replace0
Com_replace_select0
Com_reset0
Com_resignal0
Com_revoke0
Com_revoke_all0
Com_rollback0
Com_rollback_to_savepoint0
Com_savepoint0
Com_select2
Com_set_option0
Com_signal0
Com_show_binlog_events0
Com_show_binlogs0
Com_show_charsets0
Com_show_collations0
Com_show_create_db0
Com_show_create_event0
Com_show_create_func0
Com_show_create_proc0
Com_show_create_table0
Com_show_create_trigger0
Com_show_databases1
Com_show_engine_logs0
Com_show_engine_mutex0
Com_show_engine_status0
Com_show_events0
Com_show_errors0
Com_show_fields0
Com_show_function_code0
Com_show_function_status0
Com_show_grants0
Com_show_keys0
Com_show_master_status0
Com_show_open_tables0
Com_show_plugins0
Com_show_privileges0
Com_show_procedure_code0
Com_show_procedure_status0
Com_show_processlist0
Com_show_profile0
Com_show_profiles0
Com_show_relaylog_events0
Com_show_slave_hosts0
Com_show_slave_status0
Com_show_status1
Com_show_storage_engines0
Com_show_table_status0
Com_show_tables0
Com_show_triggers0
Com_show_variables0
Com_show_warnings0
Com_show_create_user0
Com_shutdown0
Com_slave_start0
Com_slave_stop0
Com_group_replication_start0
Com_group_replication_stop0
Com_stmt_execute0
Com_stmt_close0
Com_stmt_fetch0
Com_stmt_prepare0
Com_stmt_reset0
Com_stmt_send_long_data0
Com_truncate0
Com_uninstall_plugin0
Com_unlock_tables0
Com_update0
Com_update_multi0
Com_xa_commit0
Com_xa_end0
Com_xa_prepare0
Com_xa_recover0
Com_xa_rollback0
Com_xa_start0
Com_stmt_reprepare0
CompressionOFF
Connection_errors_accept0
Connection_errors_internal0
Connection_errors_max_connections0
Connection_errors_peer_address0
Connection_errors_select0
Connection_errors_tcpwrap0
Connections4
Created_tmp_disk_tables0
Created_tmp_files5
Created_tmp_tables1
Delayed_errors0
Delayed_insert_threads0
Delayed_writes0
Flush_commands1
Handler_commit0
Handler_delete0
Handler_discover0
Handler_external_lock0
Handler_mrr_init0
Handler_prepare0
Handler_read_first0
Handler_read_key0
Handler_read_last0
Handler_read_next0
Handler_read_prev0
Handler_read_rnd0
Handler_read_rnd_next21
Handler_rollback0
Handler_savepoint0
Handler_savepoint_rollback0
Handler_update0
Handler_write20
Innodb_buffer_pool_dump_statusDumping of buffer pool not started
Innodb_buffer_pool_load_statusBuffer pool(s) load completed at 201126 20:19:10
Innodb_buffer_pool_resize_status
Innodb_buffer_pool_pages_data490
Innodb_buffer_pool_bytes_data8028160
Innodb_buffer_pool_pages_dirty0
Innodb_buffer_pool_bytes_dirty0
Innodb_buffer_pool_pages_flushed37
Innodb_buffer_pool_pages_free7697
Innodb_buffer_pool_pages_misc4
Innodb_buffer_pool_pages_total8191
Innodb_buffer_pool_read_ahead_rnd0
Innodb_buffer_pool_read_ahead0
Innodb_buffer_pool_read_ahead_evicted0
Innodb_buffer_pool_read_requests5388
Innodb_buffer_pool_reads456
Innodb_buffer_pool_wait_free0
Innodb_buffer_pool_write_requests515
Innodb_data_fsyncs7
Innodb_data_pending_fsyncs0
Innodb_data_pending_reads0
Innodb_data_pending_writes0
Innodb_data_read7541248
Innodb_data_reads526
Innodb_data_writes54
Innodb_data_written641024
Innodb_dblwr_pages_written2
Innodb_dblwr_writes1
Innodb_log_waits0
Innodb_log_write_requests0
Innodb_log_writes2
Innodb_os_log_fsyncs4
Innodb_os_log_pending_fsyncs0
Innodb_os_log_pending_writes0
Innodb_os_log_written1024
Innodb_page_size16384
Innodb_pages_created35
Innodb_pages_read455
Innodb_pages_written37
Innodb_row_lock_current_waits0
Innodb_row_lock_time0
Innodb_row_lock_time_avg0
Innodb_row_lock_time_max0
Innodb_row_lock_waits0
Innodb_rows_deleted0
Innodb_rows_inserted0
Innodb_rows_read8
Innodb_rows_updated0
Innodb_num_open_files62
Innodb_truncated_status_writes0
Innodb_available_undo_logs128
Key_blocks_not_flushed0
Key_blocks_unused6695
Key_blocks_used3
Key_read_requests6
Key_reads3
Key_write_requests0
Key_writes0
Last_query_cost0
Last_query_partial_plans0
Locked_connects0
Max_execution_time_exceeded0
Max_execution_time_set0
Max_execution_time_set_failed0
Max_used_connections1
Max_used_connections_time44161.9190625
Not_flushed_delayed_rows0
Ongoing_anonymous_transaction_count0
Open_files14
Open_streams0
Open_table_definitions791
Open_tables99
Opened_files939
Opened_table_definitions0
Opened_tables0
Performance_schema_accounts_lost0
Performance_schema_cond_classes_lost0
Performance_schema_cond_instances_lost0
Performance_schema_digest_lost0
Performance_schema_file_classes_lost0
Performance_schema_file_handles_lost0
Performance_schema_file_instances_lost0
Performance_schema_hosts_lost0
Performance_schema_index_stat_lost0
Performance_schema_locker_lost0
Performance_schema_memory_classes_lost0
Performance_schema_metadata_lock_lost0
Performance_schema_mutex_classes_lost0
Performance_schema_mutex_instances_lost0
Performance_schema_nested_statement_lost0
Performance_schema_prepared_statements_lost0
Performance_schema_program_lost0
Performance_schema_rwlock_classes_lost0
Performance_schema_rwlock_instances_lost0
Performance_schema_session_connect_attrs_lost0
Performance_schema_socket_classes_lost0
Performance_schema_socket_instances_lost0
Performance_schema_stage_classes_lost0
Performance_schema_statement_classes_lost0
Performance_schema_table_handles_lost0
Performance_schema_table_instances_lost0
Performance_schema_table_lock_stat_lost0
Performance_schema_thread_classes_lost0
Performance_schema_thread_instances_lost0
Performance_schema_users_lost0
Prepared_stmt_count0
Qcache_free_blocks1
Qcache_free_memory1031832
Qcache_hits0
Qcache_inserts0
Qcache_lowmem_prunes0
Qcache_not_cached2
Qcache_queries_in_cache0
Qcache_total_blocks1
Queries6
Questions4
Select_full_join0
Select_full_range_join0
Select_range0
Select_range_check0
Select_scan1
Slave_open_temp_tables0
Slow_launch_threads0
Slow_queries0
Sort_merge_passes0
Sort_range0
Sort_rows0
Sort_scan0
Ssl_accept_renegotiates0
Ssl_accepts0
Ssl_callback_cache_hits0
Ssl_cipher
Ssl_cipher_list
Ssl_client_connects0
Ssl_connect_renegotiates0
Ssl_ctx_verify_depth0
Ssl_ctx_verify_mode0
Ssl_default_timeout0
Ssl_finished_accepts0
Ssl_finished_connects0
Ssl_server_not_after
Ssl_server_not_before
Ssl_session_cache_hits0
Ssl_session_cache_misses0
Ssl_session_cache_modeNONE
Ssl_session_cache_overflows0
Ssl_session_cache_size0
Ssl_session_cache_timeouts0
Ssl_sessions_reused0
Ssl_used_session_cache_entries0
Ssl_verify_depth0
Ssl_verify_mode0
Ssl_version
Table_locks_immediate99
Table_locks_waited0
Table_open_cache_hits0
Table_open_cache_misses0
Table_open_cache_overflows0
Tc_log_max_pages_used0
Tc_log_page_size0
Tc_log_page_waits0
Threads_cached0
Threads_connected1
Threads_created1
Threads_running1
Uptime6268
Uptime_since_flush_status6268
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值