MYSQL SQL优化思路和方法

MYSQL SQL优化思路和方法

  • 一、优化SQL的一般步骤
    • 1.1 了解各种SQL执行频率
    • 1.2 定位执行效率较低SQL
    • 1.3 Explain分析低效SQL执行计划
    • 1.4 确定问题并采取相应的优化措施
  • 二、索引问题
    • 2.1 索引的存储分类
    • 2.2 如何使用索引
      • 2.2.1 使用索引
      • 2.2.2 存在索引但不使用索引
      • 2.2.3 查看索引使用情况
    • 2.3 简单实用的优化方法
      • 2.3.1 定期分析表和检查表
      • 2.3.2 定期优化表
    • 2.4 常用SQL优化
      • 2.4.1 大批量插入数据
      • 2.4.2 优化INSERT语句
      • 2.4.3 优化GROUP BY语句
      • 2.4.4 优化ORDER BY语句
      • 2.4.5 优化嵌套查询
      • 2.4.6 优化OR条件
      • 2.4.6 使用SQL提示
  • 三、小结

一、优化SQL的一般步骤

1.1 了解各种SQL执行频率

Mysql客户端成功连接之后,通过show [global | session]命令可以提供服务器状态信息,也可以在操作系统上使用mysqladmin extended-status命令来获得这些消息。

mysql> show status like '%Com_%';
+-----------------------------+-------+
| Variable_name               | Value |
+-----------------------------+-------+
| Com_admin_commands          | 0     |
| Com_assign_to_keycache      | 0     |
| Com_alter_db                | 0     |
| Com_alter_db_upgrade        | 0     |
| Com_alter_event             | 0     |
| Com_alter_function          | 0     |
| Com_alter_instance          | 0     |
| Com_alter_procedure         | 0     |
| Com_alter_server            | 0     |
| Com_alter_table             | 0     |
| Com_alter_tablespace        | 0     |
| Com_alter_user              | 0     |
| Com_analyze                 | 0     |
| Com_begin                   | 0     |
| Com_binlog                  | 0     |
| Com_call_procedure          | 0     |
| Com_change_db               | 0     |
| Com_change_master           | 0     |
| Com_change_repl_filter      | 0     |
| Com_check                   | 0     |
| Com_checksum                | 0     |
| Com_commit                  | 0     |
| Com_create_db               | 0     |
| Com_create_event            | 0     |
| Com_create_function         | 0     |
| Com_create_index            | 0     |
| Com_create_procedure        | 0     |
| Com_create_server           | 0     |
| Com_create_table            | 0     |
| Com_create_trigger          | 0     |
| Com_create_udf              | 0     |
| Com_create_user             | 0     |
| Com_create_view             | 0     |
| Com_dealloc_sql             | 0     |
| Com_delete                  | 0     |
| Com_delete_multi            | 0     |
| Com_do                      | 0     |
| Com_drop_db                 | 0     |
| Com_drop_event              | 0     |
| Com_drop_function           | 0     |
| Com_drop_index              | 0     |
| Com_drop_procedure          | 0     |
| Com_drop_server             | 0     |
| Com_drop_table              | 0     |
| Com_drop_trigger            | 0     |
| Com_drop_user               | 0     |
| Com_drop_view               | 0     |
| Com_empty_query             | 0     |
| Com_execute_sql             | 0     |
| Com_explain_other           | 0     |
| Com_flush                   | 0     |
| Com_get_diagnostics         | 0     |
| Com_grant                   | 0     |
| Com_ha_close                | 0     |
| Com_ha_open                 | 0     |
| Com_ha_read                 | 0     |
| Com_help                    | 0     |
| Com_insert                  | 0     |
| Com_insert_select           | 0     |
| Com_install_plugin          | 0     |
| Com_kill                    | 0     |
| Com_load                    | 0     |
| Com_lock_tables             | 0     |
| Com_optimize                | 0     |
| Com_preload_keys            | 0     |
| Com_prepare_sql             | 0     |
| Com_purge                   | 0     |
| Com_purge_before_date       | 0     |
| Com_release_savepoint       | 0     |
| Com_rename_table            | 0     |
| Com_rename_user             | 0     |
| Com_repair                  | 0     |
| Com_replace                 | 0     |
| Com_replace_select          | 0     |
| Com_reset                   | 0     |
| Com_resignal                | 0     |
| Com_revoke                  | 0     |
| Com_revoke_all              | 0     |
| Com_rollback                | 0     |
| Com_rollback_to_savepoint   | 0     |
| Com_savepoint               | 0     |
| Com_select                  | 0     |
| Com_set_option              | 0     |
| Com_signal                  | 0     |
| Com_show_binlog_events      | 0     |
| Com_show_binlogs            | 0     |
| Com_show_charsets           | 0     |
| Com_show_collations         | 0     |
| Com_show_create_db          | 0     |
| Com_show_create_event       | 0     |
| Com_show_create_func        | 0     |
| Com_show_create_proc        | 0     |
| Com_show_create_table       | 0     |
| Com_show_create_trigger     | 0     |
| Com_show_databases          | 0     |
| Com_show_engine_logs        | 0     |
| Com_show_engine_mutex       | 0     |
| Com_show_engine_status      | 0     |
| Com_show_events             | 0     |
| Com_show_errors             | 0     |
| Com_show_fields             | 0     |
| Com_show_function_code      | 0     |
| Com_show_function_status    | 0     |
| Com_show_grants             | 0     |
| Com_show_keys               | 0     |
| Com_show_master_status      | 0     |
| Com_show_open_tables        | 0     |
| Com_show_plugins            | 0     |
| Com_show_privileges         | 0     |
| Com_show_procedure_code     | 0     |
| Com_show_procedure_status   | 0     |
| Com_show_processlist        | 0     |
| Com_show_profile            | 0     |
| Com_show_profiles           | 0     |
| Com_show_relaylog_events    | 0     |
| Com_show_slave_hosts        | 0     |
| Com_show_slave_status       | 0     |
| Com_show_status             | 3     |
| Com_show_storage_engines    | 0     |
| Com_show_table_status       | 0     |
| Com_show_tables             | 0     |
| Com_show_triggers           | 0     |
| Com_show_variables          | 0     |
| Com_show_warnings           | 0     |
| Com_show_create_user        | 0     |
| Com_shutdown                | 0     |
| Com_slave_start             | 0     |
| Com_slave_stop              | 0     |
| Com_group_replication_start | 0     |
| Com_group_replication_stop  | 0     |
| Com_stmt_execute            | 0     |
| Com_stmt_close              | 0     |
| Com_stmt_fetch              | 0     |
| Com_stmt_prepare            | 0     |
| Com_stmt_reset              | 0     |
| Com_stmt_send_long_data     | 0     |
| Com_truncate                | 0     |
| Com_uninstall_plugin        | 0     |
| Com_unlock_tables           | 0     |
| Com_update                  | 0     |
| Com_update_multi            | 0     |
| Com_xa_commit               | 0     |
| Com_xa_end                  | 0     |
| Com_xa_prepare              | 0     |
| Com_xa_recover              | 0     |
| Com_xa_rollback             | 0     |
| Com_xa_start                | 0     |
| Com_stmt_reprepare          | 0     |
| Compression                 | OFF   |
| Flush_commands              | 1     |
| Handler_commit              | 0     |
+-----------------------------+-------+
151 rows in set (0.00 sec)

针对的是所有存储引擎的表:
Com_select:执行select操作的次数,1次查询累计加1;
Com_insert:执行insert操作的次数,批量insert操作,只累加1;
Com_update:执行update操作的次数;
Com_delete:执行delete操作的次数。

针对Innodb存储引擎的表:
innodb_rows_read:select查询返回的行数;
innodb_row_inserted:执行insert操作插入的行数;
innodb_rows_updated:执行update操作更新的行数;
innodb_rows_deleted:执行deleted操作删除的行数。

针对事务型的应用:
Com_commit:事务提交的次数
Com_rollback:事务回滚的次数

了解数据库基本情况
Connections:视图连接Mysql服务器的次数;
Uptime:服务器工作时间;
Slow_queries:慢查询的次数。

1.2 定位执行效率较低SQL

可以通过如下两种方式定位效率较低的SQL语句:

  1. show processlist查看当前运行的线程,包括线程状态,是否锁表等;
  2. 通过慢查询日志定位低效率SQL。

1.3 Explain分析低效SQL执行计划

mysql> EXPLAIN-> SELECT->     c.name AS CustomerName,->     COUNT(o.id) AS NumberOfOrders,->     SUM(o.amount) AS TotalSpent,->     MAX(o.order_date) AS LastOrderDate-> FROM->     customers c-> JOIN->     orders o ON c.id = o.customer_id-> WHERE->     o.order_date >= DATE_SUB(CURDATE(), INTERVAL 1 YEAR)-> GROUP BY->     c.id, c.name-> HAVING->     SUM(o.amount) > 1000-> ORDER BY->     TotalSpent DESC;
+----+-------------+-------+------------+--------+---------------+---------+---------+----------------------+-------+----------+----------------------------------------------+
| id | select_type | table | partitions | type   | possible_keys | key     | key_len | ref                  | rows  | filtered | Extra                                        |
+----+-------------+-------+------------+--------+---------------+---------+---------+----------------------+-------+----------+----------------------------------------------+
|  1 | SIMPLE      | o     | NULL       | ALL    | customer_id   | NULL    | NULL    | NULL                 | 10294 |    33.33 | Using where; Using temporary; Using filesort |
|  1 | SIMPLE      | c     | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | sbtest.o.customer_id |     1 |   100.00 | NULL                                         |
+----+-------------+-------+------------+--------+---------------+---------+---------+----------------------+-------+----------+----------------------------------------------+
2 rows in set, 1 warning (0.00 sec)

select_type:表示select的类型,常见的取值有:

SIMPLE:简单表,不使用表连接或者子查询
PRIMARY:主查询,即外层的查询
UNION:UNION中的第二个或者后面的查询语句
SUBQUERY:子查询中的第一个SELECT

table:输出结果集的表
type:表的连接类型,性能由好到差的连接类型为:

system:表中仅有一行,即常量表
const:单表中最多一个匹配行,例如primary key或者unique index
eq_ref:对于前面的每一行,在此表中只查询一条记录,简单来说就是多表连接中使用primary key或者unique index
ref:与eq_ref类似,区别在于不是使用primary key或者unique index,而是普通的索引
ref_or_null,与ref类似,区别在于条件中包含对null的查询
index_merge:索引合并优化
unique_subquery:in的后面是一个查询主键字段的子查询
index_subquery:与unique_subquery类似,区别在于in的后面是查询非唯一索引字段的子查询
range:单表中的范围查询
index:对于前面的每一行,都通过查询索引来获得数据
all:对于前面的每一行,都通过全表扫描来获得数据

possible_keys:表示查询时,可能使用的索引
key:表示实际使用的索引
key_len:索引字段的长度
rows:扫描行的数量
extra:执行情况的说明和描述

1.4 确定问题并采取相应的优化措施

经过上述步骤,基本就可以确认问题出现的原因,此时可以根据情况采取相应的措施,并进行优化以提高效率。

二、索引问题

2.1 索引的存储分类

myisam存储引擎的表数据和索引是分开存储的,各自是一个独立的文件,innodb存储引擎的表数据和索引是存储在同一个表空间里边,但可以有多个文件组成。
mysql中索引的存储类型目前只有2种,BTREE和HASH,具体和表的存储引擎相关。
myisam和innodb存储引擎都支持BTREE索引,memory/heap存储引擎可以支持hash和btree索引。
mysql目前还不支持函数索引,但是可以对列的前面某一部分进行索引(前缀索引),该特性可以大大减少索引文件的大小。

2.2 如何使用索引

索引可以快速找出在某个列中有一特定值的行,对相关列使用索引是提高select操作性能的最佳途径。
查询要使用索引最主要的条件是查询条件中需要使用索引关键字,如果是多列索引,那么只有查询条件使用了多列关键字最左边的前缀时,才可以使用索引,否则不能使用索引

2.2.1 使用索引

  1. 创建的多列索引,只要查询条件中使用到了最左边的列,索引一般就会被使用。如果只选取其中的某个非最左列做条件查询,那么索引则不会用到。
mysql> create index idx_t1 on orders(order_date,amount);mysql> show index from orders;
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table  | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| orders |          0 | PRIMARY  |            1 | id          | A         |       10294 |     NULL | NULL   |      | BTREE      |         |               |
| orders |          1 | idx_cid  |            1 | customer_id | A         |        6305 |     NULL | NULL   |      | BTREE      |         |               |
| orders |          1 | idx_t1   |            1 | order_date  | A         |         730 |     NULL | NULL   |      | BTREE      |         |               |
| orders |          1 | idx_t1   |            2 | amount      | A         |       10003 |     NULL | NULL   |      | BTREE      |         |               |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
4 rows in set (0.00 sec)mysql> explain select * from orders where order_date = '2024-5-10';
+----+-------------+--------+------------+------+---------------+--------+---------+-------+------+----------+-------+
| id | select_type | table  | partitions | type | possible_keys | key    | key_len | ref   | rows | filtered | Extra |
+----+-------------+--------+------------+------+---------------+--------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | orders | NULL       | ref  | idx_t1        | idx_t1 | 3       | const |   13 |   100.00 | NULL  |
+----+-------------+--------+------------+------+---------------+--------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)mysql> explain select * from orders where amount = 1851.69;
+----+-------------+--------+------------+------+---------------+------+---------+------+-------+----------+-------------+
| id | select_type | table  | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |
+----+-------------+--------+------------+------+---------------+------+---------+------+-------+----------+-------------+
|  1 | SIMPLE      | orders | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 10294 |    10.00 | Using where |
+----+-------------+--------+------------+------+---------------+------+---------+------+-------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
  1. 对于使用like的查询,后边如果是常量并且只有%号不在第一个字符的时候,索引才可能会被使用
mysql> create index idx_name on customers(name);mysql> explain select * from customers where name like '%1';
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | customers | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 9809 |    11.11 | Using where |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)mysql> explain select * from customers where name like 'Customer_101%';
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | customers | NULL       | ALL  | idx_name      | NULL | NULL    | NULL | 9809 |    49.99 | Using where |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
  1. 如果对于大的文本进行搜索,使用全文索引而不是用like ‘%…%’
  2. 如果列名是索引,使用column_name is null将使用索引

2.2.2 存在索引但不使用索引

  1. 如果mysql认为使用索引比全表扫描更慢,则不使用索引。
  2. 如果使用memory/heap表并且where条件中不使用“=”进行索引列,那么不会用到索引。
  3. 用or分隔开的条件,如果or前的条件列有索引,而后边的列没有索引,那么涉及的索引都不会被用到。
  4. 如果不是索引列的第一部分
  5. 如果like是%开始
  6. 如果列类型是字符串,那么一定记得在where条件中把字符常量用引号引起来,否则即使该列有索引也不会用到

2.2.3 查看索引使用情况

如果索引正在工作,handler_read_key的值将会很高,这个值代表了一个行被索引值读的次数,很低的值表明增加索引得到的性能改善不高,因为索引并不经常使用。
handler_read_rnd_next的值很高,说明查询运行抵消,应该创建索引补救,这个值的含义是在数据文件中读下一行的请求数。如果正在进行大量的表扫描,Handler_read_rnd_ndext的值较高,则通常说明表索引不正确或写入的查询没有利用索引。

mysql>  show status like 'handler_read%';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| Handler_read_first    | 4     |
| Handler_read_key      | 4     |
| Handler_read_last     | 0     |
| Handler_read_next     | 10003 |
| Handler_read_prev     | 0     |
| Handler_read_rnd      | 0     |
| Handler_read_rnd_next | 10030 |
+-----------------------+-------+

2.3 简单实用的优化方法

2.3.1 定期分析表和检查表

如下语句可以用于分析和存储表的关键字分布,分析的结果将可以使系统得到准确的统计信息,使用SQL能够生成正常的执行计划。
在分析期间,使用一个读取锁定对表进行锁定,这时对myisam、bdb和innodb表有作用,但是对于myisam表,这条语句与myisamchk -a相当。

analyze [local | no_write_to_binlog] table table_name1 [, table_name2]...mysql> analyze table orders;
+---------------+---------+----------+----------+
| Table         | Op      | Msg_type | Msg_text |
+---------------+---------+----------+----------+
| sbtest.orders | analyze | status   | OK       |
+---------------+---------+----------+----------+
1 row in set (0.01 sec)mysql> analyze no_write_to_binlog table orders;
+---------------+---------+----------+----------+
| Table         | Op      | Msg_type | Msg_text |
+---------------+---------+----------+----------+
| sbtest.orders | analyze | status   | OK       |
+---------------+---------+----------+----------+
1 row in set (0.02 sec)·· 检查一个表有没有问题
mysql> check table orders;
+---------------+-------+----------+----------+
| Table         | Op    | Msg_type | Msg_text |
+---------------+-------+----------+----------+
| sbtest.orders | check | status   | OK       |
+---------------+-------+----------+----------+
1 row in set (0.03 sec)

检查表的作用是检查一个或多个表是否有错误,check table 对myisam表和innodb表有作用,对于myisam表,关键字统计数据被更新。
mysql> check table orders;
±--------------±------±---------±---------+
| Table | Op | Msg_type | Msg_text |
±--------------±------±---------±---------+
| sbtest.orders | check | status | OK |
±--------------±------±---------±---------+
1 row in set (0.03 sec)

2.3.2 定期优化表

如果已经删除了表的一大部分,或者如果已经对含有可变长度的表(含varchar、blob或text列的表)进行了很多更改,则应使用optimize table命令进行表优化。这个命令可以将表中的空间碎片进行合并,并且可以消除由于删除或者更新造成的空间浪费,但optimize table只对myisam、bob和innodb表起作用。

mysql> optimize table orders;
+---------------+----------+----------+-------------------------------------------------------------------+
| Table         | Op       | Msg_type | Msg_text                                                          |
+---------------+----------+----------+-------------------------------------------------------------------+
| sbtest.orders | optimize | note     | Table does not support optimize, doing recreate + analyze instead |
| sbtest.orders | optimize | status   | OK                                                                |
+---------------+----------+----------+-------------------------------------------------------------------+
2 rows in set (0.41 sec)

2.4 常用SQL优化

2.4.1 大批量插入数据

当用load命令导入数据的时候,可以用如下方式提高导入速度。

  1. myisam:
    disable keys和enable keys用来打开或者关闭myisam表非唯一索引的更新。
    在导入大量的数据到一个非空的myisam表时,可以通过设置这两个命令,可以提高导入的效率。
    在导入大量数数据到一个空的myisam表时,默认就是先导入数据然后才创建索引,此时就不需要设置。
alter table table_name disable keys;
loading the data...
alter table table_name enable keys;
  1. innodb:
    innodb类型的表是按照主键顺序进行保存的,所以将导入的数据按照主键的顺序进行排列;
    导入数据之前执行set unique_checks=0,关闭唯一性校验,导入结束之后在执行set unique_checks=1恢复唯一性校验;
    应用使用自动提交的方式,建议在导入前执行set autocommit=0关闭自动提交,导入结束后再执行set autocommit=1打开自动提交。

2.4.2 优化INSERT语句

  1. 如果同时从同一客户端插入很多行,尽量使用多个值表的insert语句,这种方式将大大减少客户端与数据库之间的连接、关闭等消耗;
  2. 如果从不同客户端插入很多行,能通过使用insert delayed语句得到更高的速度;delayed的含义是让insert语句马上执行;其实数据都被放在内存的队列中,并没有真正写入磁盘,比每条语句分别插入要快的多;low_priority刚好相反,在所有其他用户对表的读写完后才进行插入;
  3. 将索引文件和数据文件分在不同的磁盘上存放(利用建表的选项);
  4. 如果进行批量插入,可以增加bulk_insert_buffer_size变量值的方法来提高速度,但是这只对myisam表使用;
  5. 当从一个文本文件装载一个表时,使用load data infile,这通常比insert语句快20倍。

2.4.3 优化GROUP BY语句

默认情况下,mysql对所有group by col1,col2…的字段进行排序,这与在查询中指定order by col1,col2…类似。如果查询包括group by,但是想要避免排序结果的消耗,可以指定order by null禁止排序;

mysql> explain select address  from customers group by address;
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+---------------------------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                           |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+---------------------------------+
|  1 | SIMPLE      | customers | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 9809 |   100.00 | Using temporary; Using filesort |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+---------------------------------+
1 row in set, 1 warning (0.00 sec)mysql> explain select address  from customers group by address order by null;
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-----------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra           |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-----------------+
|  1 | SIMPLE      | customers | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 9809 |   100.00 | Using temporary |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-----------------+
1 row in set, 1 warning (0.00 sec)

2.4.4 优化ORDER BY语句

在某些情况中,mysql使用一个索引来满足order by子句,而不需要额外的排序,where条件和order by使用相同的索引。并且order by的顺序和索引顺序相同,并且order by的字段都是升序或者都是降序。

2.4.5 优化嵌套查询

mysql 4.1开始支持sql子查询,这个技术可以使用 SELECT 语句来创建一个单列的查询结果,然后把这个结果作为过滤条件用在另一个查询中。使用子查询可以一次性地完成很多逻辑上需要多个步骤才能完成的 SQL 操作,同时也可以避免事务或者表锁死,并且写起来也很容易。
但是,有些情况下,子查询可以被更有效率的连接(JOIN)替代。

2.4.6 优化OR条件

对于含有 OR 的查询子句,如果要利用索引,则 OR 之间的每个条件列都必须用到索引;
如果没有索引,则应该考虑增加索引。

2.4.6 使用SQL提示

SQL 提示(SQL HINT)是优化数据库的一个重要手段,简单来说就是在 SQL 语句中加入一些人为的提示来达到优化操作的目的。
下面是一个使用 SQL 提示的例子:

SELECT SQL_BUFFER_RESULTS * FROM...

这个语句将强制 MySQL 生成一个临时结果集。只要临时结果集生成后,所有表上的锁定均被释放。
这能在遇到表锁定问题时或要花很长时间将结果传给客户端时有所帮助,因为可以尽快释放锁资源。

  1. use index
    在查询语句中表名的后面,添加 USE INDEX 来提供希望 MySQL 去参考的索引列表,就可以让 MySQL 不再考虑其他可用的索引。
  2. ignore_index
    如果用户只是单纯地想让 MySQL 忽略一个或者多个索引,则可以使用 IGNORE INDEX 作为 HINT。同样是上面的例子,这次来看一下查询过程忽略索引 ind_sales2_id 的情况:
  3. force_index
    为强制 MySQL 使用一个特定的索引,可在查询中使用 FORCE INDEX 作为 HINT。
    例如,当不强制使用索引的时候,因为 id 的值都是大于 0 的,因此 MySQL 会默认进行全表扫描,而不使用索引。
    但是,当使用 FORCE INDEX 进行提示时,即便使用索引的效率不是最高,MySQL 还是选择使用了索引,这是 MySQL 留给用户的一个自行选择执行计划的权力。

三、小结

SQL 优化问题是数据库性能优化最基础也是最重要的一个问题,实践表明很多数据库性能问题都是由不合适的 SQL 语句造成。本章通过实例描述了 SQL 优化的一般过程,从定位一个有性能问题的 SQL 语句到分析产生性能问题的原因,最后到采取什么措施优化 SQL 语句的性能。另外还介绍了优化 SQL 语句经常需要考虑的几个方面,比如索引、表分析、排序等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/10326.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue3:路由

1. 路由简介 在Vue3中,路由是一个核心概念,特别是在构建单页面应用程序(SPA)时。以下是Vue3中路由的基本概念: 1. **路由(Route)**:在Vue3中,路由是指根据特定的规则将用…

行业新应用:电机驱动将成为机器人的动力核心

电机已经遍布当今社会人们生活的方方面面,不仅应用范围越来越广,更新换代的速度也日益加快。按照工作电源分类,可以将它划分为直流电机和交流电机两大类型。直流电机中,按照线圈类型分类,又可以分为有铁芯的电机、空心…

java日常选择题

题目来自牛客网 1.以下哪个接口的定义是正确的?() A interface B { void print() {} ;} B interface B { static void print();} C.abstract interface B extends A1, A2 //A1、A2为已定义的接口 {abstract void print(){};} D.interface B { void print(); 选D,因…

一对多在线教育系统,疫情后,在线教育有哪些变革?

疫情期间,全面开展的在线教育经历了从不适应到认可投入并常态化的发展过程。如何发挥在线教学优势,深度融合线上与线下教育,将在线教育作为育人方式变革动力,提升育人服务水平,是复学复课后学校教育教学面临的关键问题…

ARM单片机实现流水灯(GD32)

根据上图可知使用的引脚分别是PA8,PE6,PF6流水灯功能的实现要分别初始化这几个引脚 流水灯实现 编写流水灯代码 LED.C #include "gd32f30x.h" // Device header #include "Delay.h" // 初始化LED灯 void LED_Init(void){// 使能RCU时钟…

6 Shell脚本的条件测试与比较

已知:$?执行命令后 返回0 表示真 返回1 表示假 6.1.1条件测试 常用的语法 条件表达式语法 说明 1 test <测试表示式> test命令与后面表达式最少一个空格 等同于2 2 [ <测试表示式> ] []边界与内容左右2边最…

记录一次pods 导入 SocketRocket库的经历

折腾一上午&#xff0c;brew 安装成功了 cococapod 然后项目启动下载一个SocketRocket库 下载成功后总是报错&#xff1a; 睡了2个多小时&#xff0c;我在qq就交流群里求助&#xff1a; 终于把项目管理&#xff0c;在命令行里执行这句&#xff1a; open chat_app.xcworkspace…

Linux进程间通信 pipe 实现线程池 命名管道 实现打印日志 共享内存代码验证 消息队列 信号量

文章目录 前言管道匿名管道 pipe测试管道接口 --> 代码验证管道的4种情况管道的5种特征 线程池案例代码实现&#xff1a;ProcessPool.ccTask.hpp检测脚本makefile 命名管道代码演示&#xff1a;makefilenamedPipe.hppserver.ccclient.cc 实现日志Log.hpp 共享内存共享内存原…

JavaWeb后端基础知识(2)包括(MyBatis)

JavaWeb后端基础知识&#xff08;2&#xff09; 目录 JavaWeb后端基础知识&#xff08;2&#xff09; 一. MyBatis 1.什么是Mybatis? 2.步骤 &#xff08;1&#xff09;准备工作 &#xff08;2&#xff09;引入Mybatis的相关依赖&#xff0c;配置Mybatis &#xff08;…

串口属性中的BM延时计时器问题

如果使用程序修改则需要修改注册表对应位置如下 第一个示例&#xff08;217&#xff09; 第二个示例&#xff08;219&#xff09; 需要注意的事情是修改前必须点查看串口名称&#xff08;例如上图是com5&#xff09; 程序修改&#xff1a; 有没有办法以编程方式更改USB <…

【力扣】63.不同路径 II

原题链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 目录 1.题目描述 2.思路分析 3.代码实现 1.题目描述 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试…

unity通过路径找到特定对象并获取指定类型组件的泛型方法

/// <summary>/// 通过路径找到指定类型的组件/// </summary>/// <param name"path">path: 指定要查找的组件所在的GameObject的路径</param>/// <param name"parent">parent: 指定查找的GameObject的父对象&#xff0c;默认…

uniapp管理后台编写,基于uniadmin和vue3实现uniapp小程序的管理后台

一&#xff0c;创建uniAdmin项目 打开开发者工具Hbuilder,然后点击左上角的文件&#xff0c;点新建&#xff0c;点项目。如下图。 选择uniadmin&#xff0c;编写项目名&#xff0c;然后使用vue3 记得选用阿里云服务器&#xff0c;因为最便宜 点击创建&#xff0c;等待项目创…

Codeforces Round 605 (Div. 3) A~D

本人水平不高&#xff0c;开这个专栏主要是督促自己补题&#xff0c;有些题对目前的我来说还比较难&#xff0c;还补不动&#xff0c;等以后能力上来了再补。。。 原题链接&#xff1a;Dashboard - Codeforces Round 605 (Div. 3) - Codeforces 目录 A. Three Friends B. Sn…

Linux端口状态含义(未完

前言 在面试或者企业实战中常见的命令 那就是查询端口命令是哪个 1. 前沿知识 查询端口命令&#xff1a;lsof -i 查询端口的状态&#xff1a;netstat 命令参数说明-tTCP端口-uUDP端口-p进程表示符和程序名称-n显示IP 常用的netstat结合grep进行精准查询 添加链接描述 添…

C# 快速把List<string>集合转换成一个字符串

在C#中&#xff0c;要将List<string>类型的集合转换成一个单一的字符串&#xff0c;其中各元素由特定的分隔符连接&#xff0c;通常推荐使用String.Join()方法。 简单的示例&#xff1a; 使用for循环 代码如下&#xff1a; using System; using System.Collections.G…

【Linux:lesson1】的基本指令

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;Linux课程学习 &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 &#x1f697;打开Xshell&#xff0c;登陆root…

初识java--javaSE(3)--方法,递归,数组,

文章目录 一 方法的使用1.1 什么是方法&#xff1f;main方法注意事项 1.2 方法的调用嵌套调用在方法调用时形参与实参的关系&#xff1a; 1.3 方法的重载方法重载的意义&#xff1f;总结方法重载&#xff1a;方法签名&#xff1a; 二 递归什么是递归&#xff1f;递归的精髓&…

蛋糕店做配送小程序的作用是什么

蛋糕烘焙除了生日需要&#xff0c;对喜吃之人来说往往复购率较高&#xff0c;除线下实体店经营外&#xff0c;更多的商家选择线上多种方式获客转化、持续提高生意营收&#xff0c;而除了进驻第三方平台外&#xff0c;构建品牌私域自营店铺也同样重要。 运用【雨科】平台搭建蛋…

ABAP跨client的RFC调用

1、SM59配置连接 2、创建需要调用的函数&#xff0c;ZGET_TM_LIST&#xff0c;开启远程启用模块 3、新建调用程序 DATA:L_MSG TYPE C,LSH(30) TYPE C. DATA:IT_ZSTM_LIST TYPE STANDARD TABLE OF ZSTM_LIST WITH HEADER LINE.CALL FUNCTION ZGET_TM_LIST DESTINATION ZTEST_R…