MYSQL进阶(一)
1)MYSQL的體系結構圖:
1)最上面是客戶端連接器,Java語言連接數據庫用JDBC等等
2)MYSQL服務端的體系結構:
2.1)連接層主要是對連接的處理(接收客戶端的連接)以及認證授權的過程,是否超過最大連接數,在咱們操作MYSQL的時候,要輸入用戶名和密碼,這時候就要在連接層進行校驗咱們的用戶名和密碼,進行校驗哪一個客戶端可以進行操作哪些數據庫,那些表;
2.2)絕大多數的服務都是在服務層完成的,DDL,DML,視圖,SQL的優化
2.3)引擎層:存儲引擎控制的就是咱們MYSQL中的存儲數據和提取數據的方式,服務器會通過API來和存儲引擎來進行通信,進行交互,索引是在存儲引擎層實現的,也就是說不同的存儲引擎,索引的結構是不一樣的,所以說存儲引擎決定了咱們數據庫中的數據如何來存,如何來取,如何來進行組織,但是最終數據庫中的數據是存在于磁盤當中的,不同的存儲引擎有不同的功能
2.4)存放數據以及索引,完成和存儲引擎之間的交互
2)MYSQL的存儲引擎:?
定義:存儲引擎就是存儲數據,建立索引,更新,查詢數據的實現方式,不同的存儲引擎,上面幾種操作的方式機制就不一樣,存儲引擎是基于表的,不是基于數據的
2.1)在創建表的時候指定存儲引擎:
create table 表名() engine=存儲引擎的名字
2.2)查看數據庫所支持的存儲引擎:show engines
1)InnoDB:支持全文索引
DML支持ACID模型,支持事務,行級鎖,提高并發訪問性能,還有支持外健約束,有內存限制(64TB)----支持事務,支持外健,支持崩潰修復和自增列
1)存儲引擎是InnoDB表的都會對應著一個xxx.ibd文件,InnDB的每一張表都會對應著這樣的一個表空間文件,存儲該表的表結構(表名,各種字段),數據和索引,里面還有一個參數叫做InnoDB_file_per_table,決定了是否有多張表共用這一個表空間文件,是一個二進制文件
2)如果說你最終對業務要求的完整性比較高,要求所有步驟只能完成成功或者完成失敗,那么優先使用InnoDB
2)MYSIM:支持表鎖,不支持行鎖,不支持外健,不支持事務,進行添加和修改操作的時候,會進行鎖表操作
有三個文件:
xxx.sdi:存儲表結構的信息
xxx.MYD:存儲數據
xxx.MYL:存儲索引
3)Memory:Memory引擎所支持的表的數據都是在內存里面的,但是由于硬件問題,斷電問題的影響,只能將這些表作為臨時表來進行使用,文件只有一個,那就是xxx.sdi:存放表結構,只是支持表鎖,批量插入速度最高----不支持全文索引
內存存放并且支持hash索引
如何根據合適的場景來進行選擇合適的存儲引擎呢?
InnoDB是MYSQL默認的存儲引擎,支持事務,支持外鍵,如果說對于事物的完整性有一定的要求,在并發條件下要求數據的一致性,數據操作除了增和查詢之外,還包含著很多的更新,刪除操作;
MYSIM:以讀和插入操作為主,很少進行更新和刪除操作,并發性不是很高
MEmory:數據庫數據保存在內存里,訪問速度很快,通常用于臨時表的緩存,就是對表的大小有限制,太大的表沒法保存在內存里面,無法保障數據的安全性
索引補充:
在MYSQL中,支持Hash索引的是Merory存儲引擎,但是InnoDb里面具有自適應Hash功能,哈希索引是InnoDB根據B+樹在指定條件下面自動創建的
1)二叉樹順序插入會形成一個鏈表,查詢性能大大降低
2)大數據情況下,層級比較深,檢索速度慢
3)對于B樹來說,無論是葉子節點還是非葉子節點,都會保存數據,這樣導致一頁中存儲的鍵值減少,要同樣保存大量數據,就會使樹的高度變高
索引的分類:
1)主鍵索引:
2)唯一索引:避免同一張表中某數據列中的某一個值重復,是可以有多個的
3)常規索引:快速定位特定數據
4)全文索引:正派索引和倒排索引
創建普通索引:create index 索引名 on表名(列名)
創建唯一索引:create unique index 索引名 on 表名(列名)
創建聯合索引:create index 索引名 on 表名(列名1,列名2......)
轉動機械閉桿通過磁頭找到對應的磁道,在通過磁道找到對應的扇區,磁頭確定的是那一面,磁道確定的是這一面的哪一圈,扇區確定的是這一面的哪一個部分數據
1)SQL執行頻次:哪一個SQL執行頻率高,那么就對哪一個SQL進行優化:
經過下面的操作,我們就可以看到當前數據庫到底是以查詢為主,還是增刪改為主,從而為數據庫優化提供參考價值
我們可以通過show global status like "com_______"(七個-)
+---------------+-------+ | Variable_name | Value | +---------------+-------+ | Com_binlog | 0 | | Com_commit | 2 | | Com_delete | 2 | | Com_insert | 20 | | Com_repair | 0 | | Com_revoke | 0 | | Com_select | 963 | | Com_signal | 0 | | Com_update | 1 | | Com_xa_end | 0 | +---------------+-------+我們從上面可以看出,SQL的執行頻率最高的是查詢操作,我們所以最要根據這類數據庫查詢操作來進行優化
2)慢查詢日志:通過這個來進行查詢那些select的操作頻次比較高,我們要針對那些SQL執行效率比較低,MYSQL的慢查詢日志記錄了所有執行時間查過了指定參數的所有SQL語句的日志,MYSQL的慢查詢日志沒有進行開啟,需要在MYSQL的配置文件里面(/ect/my.cnf)配置如下信息:
1)啟動慢查詢日志執行開關:show_query_log=1;
2)設置慢查詢的時間是2s,如果說SQL語句執行時間超過2s,就會被視為是慢查詢操作,會進行記錄慢查詢日志:long_query_time=2;
3)show variables like "slow_query_log";查詢當前數據庫是否支持慢查詢日志
慢查詢日志在linux中的路徑是:/var/lib/mysql/localhost-show.log
查詢里面的信息cat localhost-show.log
3)profile詳情:
看看當前數據庫是否支持profiles:select @@having_profiling
開啟profile操作:set profiling =1
mysql> select * from dish; +--------+--------------+-----------+ | dishID | dishName | dishMoney | +--------+--------------+-----------+ | 2 | 紅燒茄子 | 90 | | 3 | 紅燒里脊 | 100 | | 4 | 紅燒牛肉 | 700 | | 5 | 牛肉干 | 70 | +--------+--------------+-----------+ 4 rows in set (0.00 sec)mysql> show profiles; +----------+------------+--------------------+ | Query_ID | Duration | Query | +----------+------------+--------------------+ | 1 | 0.00010350 | show profies | | 2 | 0.00072225 | show tables | | 3 | 0.00054600 | select * from dish | +----------+------------+--------------------+ 通過上面的命令就可以看到MYSQL語句的耗時時間有三個常見的命令:
show profiles:查看每一條SQL的基本查詢情況
show profile?for query query_id;查看指定id的SQL的查詢情況,看看時間長短,看看哪一部分耗時時間
show profile cpu for? query query_id;
show profile for query 3; +----------------------+----------+ | Status | Duration | +----------------------+----------+ | starting | 0.000073 | | checking permissions | 0.000004 | | Opening tables | 0.000102 | | init | 0.000023 | | System lock | 0.000030 | | optimizing | 0.000002 | | statistics | 0.000008 | | preparing | 0.000006 | | executing | 0.000001 | | Sending data | 0.000187 | | end | 0.000002 | | query end | 0.000013 | | closing tables | 0.000005 | | freeing items | 0.000076 | | cleaning up | 0.000018 | +----------------------+----------+4)explain執行計劃:我們可以通過explain或者是desc命令來進行獲取到MYSQL是如何執行select語句的信息,包括select語句執行過程中如何連接和怎么連接的順序
expalin執行計劃各個字段的含義:
4.1)id:表示MYSQL查詢的序列號,表示查詢中執行select子句或者是表的操作順序(id相同,執行順序從上到下,id不同,值越大,越被先執行
現在我們針對這幾個字段來進行演示一下
創建一張學生表: 1)drop table if exists student; 2)create table student(id int primary key auto_increment, name varchar(40)); drop table if exists course; 3)create table course(courseid int primary key auto_increment, coursename varchar(50)); drop table if exists student_course; 4)create table student_course( studentid int, courseid int, foreign key (studentid) references student(id), foreign key (courseid) references course(courseid)); 5)insert into student values(1,"李佳偉"),(2,"張中軍"),(3,"張志超"); 6)insert into course values(1,"Java"),(2,"MYSQL"),(3,"C++"); 現在我們來進行查詢一下每一個人選了那些課程:mysql> select student.*,course.coursename from student_course,course,student where student.id=student_course.studentid and student_course.courseid=course.courseid; +----+-----------+------------+ | id | name | coursename | +----+-----------+------------+ | 1 | 李佳偉 | Java | | 1 | 李佳偉 | MYSQL | | 2 | 張中軍 | MYSQL | | 3 | 張志超 | Java | | 3 | 張志超 | MYSQL | | 3 | 張志超 | C++ | +----+-----------+------------+剛才我們在進行使用外鍵的時候,注意:
1)本表中的字段名也要加上括號
2)注意是references
desc select student.*,course.coursename from student_course,course,student where student.id=student_course.studentid and student_course.courseid=course.courseid; +----+-------------+----------------+------------+------+--------------------+----------+---------+---------------------------+------+----------+----------------------------------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+----------------+------------+------+--------------------+----------+---------+---------------------------+------+----------+----------------------------------------------------+ | 1 | SIMPLE | course | NULL | ALL | PRIMARY | NULL | NULL | NULL | 3 | 100.00 | NULL | | 1 | SIMPLE | student_course | NULL | ref | studentid,courseid | courseid | 5 | orderdish.course.courseid | 1 | 100.00 | NULL | | 1 | SIMPLE | student | NULL | ALL | PRIMARY | NULL | NULL | NULL | 3 | 33.33 | Using where; Using join buffer (Block Nested Loop) | +----+-------------+----------------+------------+------+--------------------+----------+---------+------------------查詢一下選擇了MYSQL課程的學生,子查詢
select courseid from course where coursename="MYSQL";select studentid from student_course where courseid=2;select name from student where id in(1,2,3); select name from student s1 where s1.id in (select studentid from student_course s2 where s2.courseid=(select courseid from course s3 where s3.coursename="MYSQL")); ----------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+--------------------+------+---------+------+------+----------+--------------------------------------------------------------------+ | 1 | PRIMARY | s1 | NULL | ALL | PRIMARY | NULL | NULL | NULL | 3 | 100.00 | NULL | | 1 | PRIMARY | s2 | NULL | ALL | studentid,courseid | NULL | NULL | NULL | 6 | 16.67 | Using where; FirstMatch(s1); Using join buffer (Block Nested Loop) | | 3 | SUBQUERY | s3 | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 33.33 | Using where | +----+-------------+-------+------------+------+--------------------+------+---------+------+------+----------+----------------------------------------------4.2)select type:表示select的類型
常見的取值有simple:簡單表,表示不進行使用表連接或者子查詢
primary:表示主查詢,即外層的查詢
union:表示union后面第二個或者后面的查詢語句
subquery:表示select where后面包括了子查詢等等
4.3)type:表示連接類型,性能由好到差的連接類型有
null(什么時候都不操作表),system(系統表),
const:把一個主鍵放在where后面進行作為條件查詢
eq_ref(在join中使用主鍵或者唯一索引),
ref(使用非唯一性索引進行查詢),
range(索引的范圍查詢),
index(代表索引覆蓋,遍歷所有的索引查找)
all(全表掃描,(通常沒有建索引的列));
4.4)possible_key:顯示可能應用在這張表上面的索引,一個或者多個
4.5)key_len:表示索引中所使用的字節數,該值可能為索引字段最大可能長度,而不是實際使用長度,在不損失精度的情況下,長度越短越好
4.6)rows:MYSQL認為必須要進行執行查詢的行數,在innodb引擎中是一個估計值,但是結果并不總是準確的
4.7)filedter:返回結果的行數占需要進行讀取行數的百分比,這個值越大性能越高
4.8)Extra:表示額外數據查詢,執行情況的描述和說明
4.9)key:表示實際使用到的索引,如果為空,那么表示從來沒有使用過索引,反之,那么使用到了索引
table:表示輸出結果的表
總結
以上是生活随笔為你收集整理的MYSQL进阶(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 上海居住证办理(闵行)
- 下一篇: 查看数据库IP地址