日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

MySQL优化之三:SQL语句优化

發(fā)布時(shí)間:2024/4/17 数据库 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL优化之三:SQL语句优化 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一 SQL語句優(yōu)化的一般步驟:

1 通過show status命令了解各種SQL語句的執(zhí)行頻率

mysql> show status;????????????????#show status:顯示服務(wù)器狀態(tài)信息

+-----------------------------------------------+-------------+

| Variable_name ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | Value ? ? ? |

+-----------------------------------------------+-------------+

| Aborted_clients ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | 0 ? ? ? ? ? |

| Aborted_connects ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| 0 ? ? ? ? ? |

| Binlog_cache_disk_use ? ? ? ? ? ? ? ? ? ? ? ? | 0 ? ? ? ? ? |

| Binlog_cache_use ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| 8 ? ? ? ? ? |

| Binlog_stmt_cache_disk_use ? ? ? ? ? ? ? ? ? ?| 0 ? ? ? ? ? |

| Binlog_stmt_cache_use ? ? ? ? ? ? ? ? ? ? ? ? | 25 ? ? ? ? ?|

| Bytes_received ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| 2919 ? ? ? ?|

| Bytes_sent ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| 51750 ? ? ? |

......

mysql> show status like "com%";????#顯示當(dāng)前session中,統(tǒng)計(jì)參數(shù)的值

+---------------------------+-------+

| 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_procedure ? ? ? | 0 ? ? |

| Com_alter_server ? ? ? ? ?| 0 ? ? |

| Com_alter_table ? ? ? ? ? | 2 ? ? |

| Com_alter_tablespace ? ? ?| 0 ? ? |

| Com_alter_user ? ? ? ? ? ?| 0 ? ? |

| Com_analyze ? ? ? ? ? ? ? | 0 ? ? |

| Com_begin ? ? ? ? ? ? ? ? | 0 ? ? |

......

Com_xxx:表示每個(gè)xxx語句執(zhí)行的次數(shù),以下幾個(gè)統(tǒng)計(jì)參數(shù)非常重要:

  • Com_select:執(zhí)行select的次數(shù),一次查詢累計(jì)加1

  • Com_insert:執(zhí)行insert操作的次數(shù),批量插入只累加1

  • Com_delete:執(zhí)行delete操作的次數(shù),

  • Com_update:執(zhí)行update操作的次數(shù),

以上參數(shù)針對所有存儲引擎的表操作。

下面的參數(shù)是針對InnoDB存儲引擎的,算法也稍有不同:

Innodb_rows_read:select查詢返回的行數(shù)

Innodb_rows_inserted:執(zhí)行insert操作插入的行數(shù)

Innodb_rows_updated:執(zhí)行update操作更新的行數(shù)

Innodb_rows_deleted:執(zhí)行delete操作刪除的行數(shù)

通過以上參數(shù)的了解,可以判斷出當(dāng)前數(shù)據(jù)庫是以插入更新為主還是以查詢操作為主,以及各種類型SQL大致的執(zhí)行比例是多少。

此外,以下幾個(gè)參數(shù)可以幫助用戶了解數(shù)據(jù)庫的基本情況:

Uptime:數(shù)據(jù)庫服務(wù)器的工作時(shí)間

Connections:試圖連接服務(wù)器的次數(shù)

Slow_queries:慢查詢的次數(shù)


2 定位執(zhí)行效率低的SQL語句

方式1:通過慢查詢?nèi)罩径ㄎ?/p>

方式2:查看當(dāng)前正在進(jìn)行的線程

mysql> show processlist;? ??

+----+-------------+-----------+------+---------+-------+-----------------------------------------------------------------------------+------------------+

| Id | User ? ? ? ?| Host ? ? ?| db ? | Command | Time ?| State ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | Info ? ? ? ? ? ? |

+----+-------------+-----------+------+---------+-------+-----------------------------------------------------------------------------+------------------+

| ?1 | system user | ? ? ? ? ? | NULL | Connect | 34400 | Waiting for master to send event ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NULL ? ? ? ? ? ? |

| ?2 | system user | ? ? ? ? ? | NULL | Connect | ?7738 | Slave has read all relay log; waiting for the slave I/O thread to update it | NULL ? ? ? ? ? ? |

| ?4 | root ? ? ? ?| localhost | NULL | Query ? | ? ? 0 | init ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| show processlist |

[root@localhost ~]# mysqladmin -uroot -h 127.0.0.1 processlist -proot

Warning: Using a password on the command line interface can be insecure.

+----+------+-----------------+----+---------+------+-------+------------------+

| Id | User | Host ? ? ? ? ? ?| db | Command | Time | State | Info ? ? ? ? ? ? |

+----+------+-----------------+----+---------+------+-------+------------------+

| 1 ?| root | localhost ? ? ? | ? ?| Sleep ? | 265 ?| ? ? ? | ? ? ? ? ? ? ? ? ?|

| 12 | root | localhost:42210 | ? ?| Query ? | 0 ? ?| init ?| show processlist |

+----+------+-----------------+----+---------+------+-------+------------------+

備注:show processlist;只列出前100條,如果想全列出請使用show full processlist;


3 通過explain分析低效的SQL語句的執(zhí)行

通過之前的步驟查詢到效率低的SQL語句之后,可以通過explain命令獲取MySQL是如何執(zhí)行select語句的信息。如:

mysql> explain select * from emp1;

+----+-------------+-------+------+---------------+------+---------+------+------+-------+

| id | select_type | table | type | possible_keys | key ?| key_len | ref ?| rows | Extra |

+----+-------------+-------+------+---------------+------+---------+------+------+-------+

| ?1 | SIMPLE ? ? ?| emp1 ?| ALL ?| NULL ? ? ? ? ?| NULL | NULL ? ?| NULL | ? ?4 | NULL ?|

+----+-------------+-------+------+---------------+------+---------+------+------+-------+

1 row in set (0.00 sec)

  • select_type——select類型

  • table——輸出結(jié)果的表

  • type——表示MySQL在表中找到所需行的方式,或者叫訪問類型,常見有以下幾種:性能由最差到最好。

type=all,即通過全表掃描找到匹配的行。

type=index,索引全掃描,mysql遍歷索引才找到匹配的行。

type=range,索引范圍掃描,

type=ref,使用非唯一索引掃描,或唯一索引的前綴掃描,返回匹配某個(gè)單獨(dú)值的記錄行

type=eq_ref,類似ref,區(qū)別在于使用的索引是唯一索引,對于每個(gè)索引鍵值,表中只有一條記錄匹配。

type=const/system,表單中最多有一個(gè)匹配行,查詢起來非常迅速。如根據(jù)主鍵和唯一索引進(jìn)行的查詢。

type=null,不需要訪問表或索引,直接就可以得到結(jié)果。

  • possible_keys——表示查詢時(shí)可能使用的索引

  • key——表示實(shí)際使用的索引

  • key_len——使用到索引字段的長度

  • rows——掃描行的數(shù)量

  • Extra——執(zhí)行情況的說明和描述


4 通過show profile了解分析SQL執(zhí)行的過程

mysql> select @@have_profiling;????????#查看是否支持

+------------------+

| @@have_profiling |

+------------------+

| YES ? ? ? ? ? ? ?|

+------------------+

mysql> set profiling=1;????????????????#開啟profiling,默認(rèn)是關(guān)閉

Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> select * from emp1;???????????? #執(zhí)行一個(gè)語句

+------+--------+-------+------------+

| age1 | deptno | ename | birth ? ? ?|

+------+--------+-------+------------+

| ?111 | ? ? ?4 | ccc ? | 2011-11-30 |

| ?666 | ? ? 11 | ddd ? | 2014-12-22 |

| ?888 | ? ? 22 | eee ? | 2015-11-30 |

| ?333 | ? ? ?8 | fff ? | 2011-04-30 |

+------+--------+-------+------------+

4 rows in set (0.02 sec)

mysql> show profiles;????????????????? #查看當(dāng)前SQL語句的查詢ID

+----------+------------+---------------------------+

| Query_ID | Duration ? | Query ? ? ? ? ? ? ? ? ? ? |

+----------+------------+---------------------------+

| ? ? ? ?1 | 0.01696625 | select count(*) from emp1 |

| ? ? ? ?2 | 0.02623125 | select * from emp1 ? ? ? ?|

+----------+------------+---------------------------+

mysql> show profile for query 2;? ? ? ?#查看執(zhí)行過程中線程的每個(gè)狀態(tài)和消耗時(shí)間

+----------------------+----------+

| Status ? ? ? ? ? ? ? | Duration |

+----------------------+----------+

| starting ? ? ? ? ? ? | 0.000111 |

| checking permissions | 0.000019 |

| Opening tables ? ? ? | 0.000046 |

| init ? ? ? ? ? ? ? ? | 0.000043 |

| System lock ? ? ? ? ?| 0.000031 |

| optimizing ? ? ? ? ? | 0.000016 |

| statistics ? ? ? ? ? | 0.000039 |

| preparing ? ? ? ? ? ?| 0.000023 |

| executing ? ? ? ? ? ?| 0.000008 |

| Sending data ? ? ? ? | 0.025442 |

| end ? ? ? ? ? ? ? ? ?| 0.000020 |

| query end ? ? ? ? ? ?| 0.000014 |

| closing tables ? ? ? | 0.000016 |

| freeing items ? ? ? ?| 0.000326 |

| cleaning up ? ? ? ? ?| 0.000079 |

+----------------------+----------+

Sending data表示MySQL線程開始訪問數(shù)據(jù)行并把結(jié)果返回給客戶端。通常是整個(gè)查詢中耗時(shí)最長的狀態(tài)

mysql> show profile cpu for query 2;????#查看耗費(fèi)CPU的時(shí)間,Sending data主要耗費(fèi)在CPU上

+----------------------+----------+----------+------------+

| Status ? ? ? ? ? ? ? | Duration | CPU_user | CPU_system |

+----------------------+----------+----------+------------+

| starting ? ? ? ? ? ? | 0.000111 | 0.000000 | ? 0.000000 |

| checking permissions | 0.000019 | 0.000000 | ? 0.000000 |

| Opening tables ? ? ? | 0.000046 | 0.000000 | ? 0.000000 |

| init ? ? ? ? ? ? ? ? | 0.000043 | 0.000000 | ? 0.000000 |

| System lock ? ? ? ? ?| 0.000031 | 0.000000 | ? 0.000000 |

| optimizing ? ? ? ? ? | 0.000016 | 0.000000 | ? 0.000000 |

| statistics ? ? ? ? ? | 0.000039 | 0.000000 | ? 0.000000 |

| preparing ? ? ? ? ? ?| 0.000023 | 0.000000 | ? 0.000000 |

| executing ? ? ? ? ? ?| 0.000008 | 0.000000 | ? 0.000000 |

| Sending data ? ? ? ? | 0.025442 | 0.000000 | ? 0.001999 |

| end ? ? ? ? ? ? ? ? ?| 0.000020 | 0.000000 | ? 0.000000 |

| query end ? ? ? ? ? ?| 0.000014 | 0.000000 | ? 0.000000 |

| closing tables ? ? ? | 0.000016 | 0.000000 | ? 0.000000 |

| freeing items ? ? ? ?| 0.000326 | 0.000000 | ? 0.000000 |

| cleaning up ? ? ? ? ?| 0.000079 | 0.000000 | ? 0.000000 |

+----------------------+----------+----------+------------+

mysql> show profile all for query 1\G ?#查看所有明細(xì),了解MySQL在什么資源上耗費(fèi)了過高的時(shí)間


5 通過trace分析優(yōu)化器如何選擇執(zhí)行計(jì)劃


6 確定問題之后,采取相應(yīng)的措施優(yōu)化

由前面的步驟確認(rèn)對表進(jìn)行全表掃描,導(dǎo)致查詢效果不理想,那么對表的某個(gè)字段建立索引。具體如下 :

mysql> create index index_ename on emp1(ename);

Query OK, 0 rows affected (0.25 sec)

Records: 0 ?Duplicates: 0 ?Warnings: 0

建立索引后,再看下這條語句的執(zhí)行狀態(tài):

mysql> explain select ename from emp1;

建立索引后,可以發(fā)現(xiàn)對表掃描的行數(shù)大大減少,提高了對表的訪問速度。


二 索引問題

索引是數(shù)據(jù)庫優(yōu)化中最重要也是最常用的手段之一,通過索引可以幫助用戶解決大多數(shù)SQL性能問題。

1 索引的存儲分類:索引是在存儲引擎層中實(shí)現(xiàn)的

  • B-Tree索引:最常見的索引,大部分引擎支持B樹索引。

  • HASH索引:只有Memory引擎支持,使用場景簡單

  • Full-text(全文索引):一種特殊索引類型

創(chuàng)建索引方式 1:

mysql>?create?index index_age1 on emp1(age1);

Query OK, 0 rows affected (0.15 sec)

Records: 0 ?Duplicates: 0 ?Warnings: 0

創(chuàng)建索引方式 2:

mysql>?alter table?zwj.emp1 add index index_ename (ename);

Query OK, 0 rows affected (0.05 sec)

Records: 0 ?Duplicates: 0 ?Warnings: 0

查看索引:

mysql> show index from zwj.emp1;

+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

| Table | Non_unique | Key_name ? ?| Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |

+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

| emp1 ?| ? ? ? ? ?1 | index_ename | ? ? ? ? ? ?1 | ename ? ? ? | A ? ? ? ? | ? ? ? ? ? 4 | ? ? NULL | NULL ? | YES ?| BTREE ? ? ?| ? ? ? ? | ? ? ? ? ? ? ? |

| emp1 ?| ? ? ? ? ?1 | index_age1 ?| ? ? ? ? ? ?1 | age1 ? ? ? ?| A ? ? ? ? | ? ? ? ? ? 4 | ? ? NULL | NULL ? | YES ?| BTREE ? ? ?| ? ? ? ? | ? ? ? ? ? ? ? |

+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

刪除索引:

mysql> drop index index_age1 on zwj.emp1;

Query OK, 0 rows affected (0.06 sec)

Records: 0 ?Duplicates: 0 ?Warnings: 0


mysql> alter table zwj.emp1 drop index index_ename;

Query OK, 0 rows affected (0.04 sec)

Records: 0 ?Duplicates: 0 ?Warnings: 0


另有復(fù)合索引:需要咨詢開發(fā)人員

創(chuàng)建復(fù)合索引(將最常用作限制條件的列放在最左邊,依次遞減):

mysql> create index name_passwd on abc.student(name,passwd);(需要咨詢研發(fā)部門)


2 查看索引的使用情況:

mysql> show status like 'handler_read%';

+-----------------------+-------+

| Variable_name ? ? ? ? | Value |

+-----------------------+-------+

| Handler_read_first ? ?| 4 ? ? |

| Handler_read_key ? ? ?| 5 ? ? |

| Handler_read_last ? ? | 0 ? ? |

| Handler_read_next ? ? | 0 ? ? |

| Handler_read_prev ? ? | 0 ? ? |

| Handler_read_rnd ? ? ?| 0 ? ? |

| Handler_read_rnd_next | 56 ? ?|

+-----------------------+-------+

7 rows in set (0.00 sec)

Handler_read_key:如果索引正在工作,此值應(yīng)該很高,這個(gè)值代表了一個(gè)行被索引值讀的次數(shù)。如果值過低,表明增加索引得到的性能改善不高,因?yàn)樗饕⒉怀1皇褂谩?/p>

Handler_read_rnd_next:值高意味著查詢運(yùn)行低效,并且應(yīng)該建立索引補(bǔ)救。這個(gè)值的含義是在數(shù)據(jù)文件中讀下一行的請求數(shù)。如果進(jìn)行了大量的掃描,它的值會很高,說明索引不正確或查詢沒有利用到索引。


本文轉(zhuǎn)自 zengwj1949 51CTO博客,原文鏈接:http://blog.51cto.com/zengwj1949/1920641

總結(jié)

以上是生活随笔為你收集整理的MySQL优化之三:SQL语句优化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。