2020面試準備之MySql優化

Mysql優化綜合性的問題:

A、表的是設計合理化(符合 3範式)

B、添加適當的索引(index)[四種:普通索引,主鍵索引,唯一索引,unique,全文索引]

C、分表技術(水平分割,垂直分割)

D、讀寫[寫:update/delete/add]分離

E、存儲過程[模塊化編程,可以提高速度]

F、對mysql配置優化[配置最大併發數,my.ini調整緩存大小]

G、Mysql服務器引薦升級

H、定時的去清楚不需要的數據,定時進行碎片整理

.1.  數據庫的表設計

第一範式:1NF是對屬性的原子性約束,要求屬性(列)具有原子性,不可再分解;(只要是關係型數據庫都滿足1NF)

第二範式:2NF是對記錄的惟一性約束,要求記錄有惟一標識,即實體的惟一性;

第三範式:3NF是對字段冗餘性的約束,它要求字段沒有冗餘。沒有冗餘的數據庫設計可以做到。

.2.  Sql優化的一般步驟:

操作步驟:

1、通過show status命令瞭解各種SQL的執行頻率。

2、 定位執行效率較低的SQL語句-(重點select)

3、 通過explain分析低效率的SQL語句的執行情況

4、確定問題並採取相應的優化措施

 

MySQL通過使用show [session|global] status 命令可以提供服務器狀態信息。

 

session來表示當前的連接的統計結果,global來表示自數據庫上次啓動至今的統計結果。默認是session級別的。

show status like ‘Com_%’;

其中Com_XXX表示XXX語句所執行的次數。Eg:Com_insert,Com_Select…
重點注意:Com_select,Com_insert,Com_update,Com_delete通過這幾個參數,可以容易地瞭解到當前數據庫的應用是以插入更新爲主還是以查詢操作爲主,以及各類的SQL大致的執行比例是多少。
Connections:試圖連接MySQL服務器的次數
Uptime:服務器工作的時間(單位秒)
Slow_queries:慢查詢的次數 (默認是慢查詢時間10s)

Show status like‘Handler_read%’使用查詢的次數

 

♥定位慢查詢:

         在默認的情況下mysql是不記錄滿查詢日誌的,需要在啓動的時候指定

         \bin\mysqld.exe- -safe-mode – slow-query-log[mysql5.5可以在my.ini中指定]

\bin\mysqld.exe- -log-slow-queries=d:bac.log

具體操作如下:

     如果啓用了慢查詢,默認存儲在mysql.ini文件的此處

      

 

         1、重啓mysql,找到datadir的路勁,使用cmd進入到data的上級目錄

         2、運行命令\bin\mysqld.exe –safe-mode  –slow-query-log(注意執行前先關閉mysql服務)

         3、生成的日誌文件記錄着所有的記錄信息

顯示慢查詢的時間:Show variables like ‘long_query_time’;

重新設置滿查詢的時間:Set long_query_time=2;

 

修改命令結束符:(爲了存儲過程能夠正常執行,我們需要把命令結束符號進行修修改)

Delimiter $$

如何把慢查詢的sql語句記錄到我們的日誌中(默認情況下mysql是不會記錄的,需要在啓動mysql的時候,指定慢查詢的)。

 

 

.3.  索引

♥索引的類型:

★四種索引①主鍵索引②唯一索引③普通索引④全文索引

       一、添加

      1.1主鍵索引添加

                   當把一張表的某列設置爲主鍵的時候,則該列就是主鍵索引。

                  Createtable aaa(id int unsigned primary key auto_increment,

                  name varchar(32) not null default);

       1.2普通索引

                  一般來說,普通索引是先創建表,然後創建普通索引。

                  比如:

                  Createindex索引名 from表名

       1.3創建全文索引

         全文索引,主要是針對文件,比如文章的索引全文索引針對MyISAM有用,針對innodb沒有用

                          Create table articles(

                          Id int unsignedauto_increment not null primary key,

                          Title varchar(20),

                          Body text,

                          Fulltext (title,body)

                          )engine=myisam charsetutf8;

                  錯誤用法:

                          Select * from articles where body like ‘%mysql%’[不會使用到全文索引]

                  證明:

                          Explain select * from articles body like ‘%mysql%’;

                  正確的用法:

                          Select * from article wherematch(title,body)against(‘database’);[可以]

                  說明:

                          1、在mysql中fulltest索引值針對myisam生效

                         2、針對英文生效,àsphinx(coreseek)技術處理中文

                          3、使用的方法,match(字段名,…)against(‘關鍵詞’)

                         4、全文索引一個叫停止詞。因爲在一個文本中,創建索引的是一個無窮大的書,因此,對一些常用詞和字符就不會創建,這些詞,稱之爲停止詞

           1.4創建唯一索引

                       當表的某列被指定爲unique約束時,這列就是唯一索引

                        第一種、Create table ddd(id int primary keyauto_increment,name varchar(32) unique);

                                    這時,name默認就是唯一索引

                        第二種、create table eee(id int primary keyauto_increment,name varchar(32));

                              Createunique index索引名 on表名(列名)

                  簡單的說:PRIMARY KEY=UNIQUE+NOT NULL

                  Unique字段可以爲null,並可以有多個null,但是如果是具體內容,則不能重複

                  主鍵字段,不能爲null,也不能重複

      二、查詢

         1.Desc表名[該方法的缺點,不能夠現實索引名]

         2.Show index from表名;

                  select index from表名\G

        3.show keys from表名

      三、刪除

         Altertable 表名 drop  index 索引名,

         Altertable 表名 drop primary key。(刪除主鍵索引名)

       四、修改

             先刪除,在全部

二、針對SQL編寫導致的慢 SQL,優化起來還是相對比較方便的。正如上一節提到的正確的使用索引能加快查詢速度,那麼我們在編寫 SQL 時就需要注意與索引相關的規則:

1.字段類型轉換導致不用索引,如字符串類型的不用引號,數字類型的用引號等,這有可能會用不到索引導致全表掃描;

2.mysql 不支持函數轉換,所以字段前面不能加函數,否則這將用不到索引;

3.不要在字段前面加減運算;

4.字符串比較長的可以考慮索引一部份減少索引文件大小,提高寫入效率;

5.like % 在前面用不到索引;

6.根據聯合索引的第二個及以後的字段單獨查詢用不到索引;

7.不要使用 select *;

8.排序請儘量使用升序 ;

9.or 的查詢儘量用 union 代替(Innodb);

10.複合索引高選擇性的字段排在前面;

11.order by / groupby 字段包括在索引當中減少排序,效率會更高。

除了上述索引使用規則外,SQL 編寫時還需要特別注意一下幾點:

1.儘量規避大事務的 SQL,大事務的 SQL 會影響數據庫的併發性能及主從同步;

2.分頁語句 limit 的問題;

3.刪除表所有記錄請用 truncate,不要用 delete;

4.不讓 mysql 幹多餘的事情,如計算;

5.輸寫 SQL 帶字段,以防止後面表變更帶來的問題,性能也是比較優的 ( 涉及到數據字典解析,請自行查詢資料);

6.在 Innodb上用 select count(*),因爲 Innodb 會存儲統計信息;

7.慎用 Oder by rand()。

三、顯示慢查詢的次數:show status like 'slow_queries';

                    

存儲類型

存儲引擎

允許的索引類型

MyISAM

BTREE

InnoDB

BTREE

MEMORY/HEAP

BTREE

HEAP是較早的mysql版本

四、Explain分析低效率的SQL語句:

             

會產生如下信息:

             select_type:表示查詢的類型。

            table:輸出結果集的表

            type:表示表的連接類型

            possible_keys:表示查詢時,可能使用的索引

            key:表示實際使用的索引

            key_len:索引字段的長度

            rows:掃描出的行數(估算的行數)

            Extra:執行情況的描述和說明

Select_type類型:

            primary : 子查詢中最外層查詢

            subquery : 子查詢內層第一個select,結果不依賴於外部查詢

            dependent subquery : 子查詢內層第一個select,依賴於外部查詢

            union:union語句中第二個select開始後面所有select

            simple: 簡單模式

            union result: union中合併結果

type 類型:

            all: 完整的表掃描 通常不好

            system : 表僅有一行(=系統表) 這是const聯接類型的一個特例

            const : 表最多有一個匹配行

extra 類型:

            no table: query語句中使用 from dual 或不含任何from子句

            Using filesort : 當query中包含 order by 操作,而且無法利用索引完成排序

             impossible WHERE noticed after readingconst tables:Mysql query optimizer

通過收集統計信息不可能存在結果

            Using temporary : 某些操作必須使用臨時表,常見 group by ,order by

            Using where: 不用讀取表中所有信息,僅通過索引就可以獲取所需數據

 

.4.  ☆★爲什麼使用了索引後查詢速度會變快

 

       普通的查詢如果沒有索引,他會一直去執行,及時匹配到了還要繼續查詢,不能保證後面有沒有要查詢的。要全文索引。

 

 

■索引使用的注意事項

索引的代價:

         1、佔用磁盤空間

2、對DML(insert,update,create)操作有影響,變慢

■總結:滿足以下條件,才應該創建索引

A、肯定在where經常使用

B、該字段的內容不是唯一的幾個值(sex)

C、字段內容不是頻繁變化

■使用索引的注意事項:

alter table dept add index myind (dname,loc); // dname就是左邊的列,loc是右邊的列

下列情況有可能使用到索引

a.對於創建的多列索引,只要查詢條件使用了最左邊的列,索引一般就會被使用 explain select * from dept where dname='aaa';

b.對於使用like的查詢,查詢條件如果是'%aaa'則不會使用到索引,'aaa%'會使用到索引

下列情況不會使用索引 :

a.如果條件中有or,即使其中有條件帶索引也不會使用換言之,就是要求使用的所有字段都創建索引,建議:儘量避免使用or關鍵字

b.對於多列索引,不是使用的第一部分,則不會使用索引

explain select * from dept where loc='aaa';// 多列索引時,loc爲右邊列,索引不會使用到

c.like查詢是以%開頭如果一定要使用,則使用全文索引去查詢

d.如果列類型是字符串,那一定要在條件中將數據使用引號引起來,否則不使用索引

e.如果MySQL估計使用全表掃描要比使用索引塊,則不使用索引

如何選擇mysql的存儲引擎
         1:myISAM

                   如果表對事務的要求不高,同事一查詢和添加爲主的,

                   比如BBS中的發帖,回帖。

2:InnoDB

         對事務的要求高,保存的數據都是重要數據,

         比如訂單,賬戶表

3:Memory:

         數據變化頻繁,不需要入庫同時又進場查詢和修改。

myISAM和InnoDB的區別:

1、myISAM批量插入快,InnoDB插入慢,myISAM插入時候不排序。

2、InnoDB支持事務,myISAM不支持事務。

3、MyISAM支持全文索引,

4、鎖機制,myISAM是表鎖,InnoDB是行鎖

5、myISAM不支持外鍵,InnoDB支持外健

① 在進度要求高的應用中,建議使用定點數據來存儲數值,組U一保證數據的準確性,deciaml進度比float高,儘量使用

②  對於存儲引擎的myISAM的數據庫,如果進場要走刪除和修改的操作,要定時執行optimize_table_name功能對錶進行碎片整理。

③  日期類型要根據實際需要選擇引用的最小存儲的早期類型,

手動備份數據庫:

1、進入cmd

2、Mysqldump –uroot –proot數據庫【表名1,表名2…】 > 文件路徑

Eg: mysqldump -uroot -proot temp > d:/temp.bak

恢復備份文件數據:

         Source d:/temp.bak(在mysql控制檯)

合理的硬件資源和操作系統

         Master

Slave1

Slave2

Slave3

         主庫master用來寫入,slave1—slave3都用來做select,每個數據庫

分擔的壓力小了很多。

要實現這種方式,需要程序特別設計,寫都操作master,讀都操作

slave,給程序開發帶來了額外負擔。當然目前已經有中間件來實現這個

代理,對程序來讀寫哪些數據庫是透明的。官方有個mysql-proxy,但是

還是alpha版本的。新浪有個amobe for mysql,也可達到這個目的,結構

如下 

.5.  表的分割

水平分割:

         大數據量的表,我們在提供檢索的時候,應該根據業務的需求,找到表的標準,並在檢索頁面約束用戶的檢索方式,而且要配合分頁,

         案例:大數據量的用戶表

三張表:qqlogin0,qqlogin1,qqlogin2

將用戶id%3,按結果放入不同的表當中

create tableqqlogin0(

       id int unsigned not null primary key,/* 這個id不能設置自增長 */

       name varchar(32)not null default'',

       pwd varchar(32)not null default''

)engine = myisam default charset = utf8;

 

創建表qqlogin1(

        id int unsigned not null主鍵,/ *這個id不能設置自增長* /

        name varchar(32)not null default'',

        pwd varchar(32)not null default''

    )engine = myisam default charset = utf8;

 

創建表qqlogin2(

        id int unsigned not null主鍵,/ *這個id不能設置自增長* /

        name varchar(32)not null default'',

        pwd varchar(32)not null default''

    )engine = myisam default charset = utf8;

垂直分割:

                   把某個表的某些字段,這些字段,在查詢時候並不關係,但是數據量很大,我們建議將這些字段放到一個表中,從而提高效率,

0.6。優化的Mysql的配置

MY.INI

port = 3306默認端口是3306,

如果想修改端口port = 3309,在mysql_connect('localhost:3309','root','root');要注意

query_cache_size = 15M這個是查詢緩存的大小

InnoDB的參數也可以調大以下兩個參數

innodb_additional_mem_pool_size = 64M

innodb_buffer_pool_size = 1G

myisam需要調整key_buffer_size

調整參數還要看狀態,用show status可以看到當前狀態,以決定該調整哪些參數

0.7。增量備份

實際案例:

         如何進行增量備份,和恢復

步驟:

如圖1所示,配置的my.ini文件或者是my.cof,啓用二進制備份

 

2,重新啓動的MySQL

啓動之後會發現mylog目錄下生成了一下文件

 

其中:E:\二進制日誌\ mylog.index索引文件,有哪些備份文件

E:\二進制日誌\ mylog.000001存放用戶對象數據庫操作的文件

3,當我們進行操作的時候(選擇)

查看需要進入到MySQL的的安裝目錄下的bin中,然後執行mysqlbinlog可以文件,後面追加文件路徑

 

 

 

如圖4所示,恢復到某個語句的時間點

4,1按照時間點回復

Mysqlbinlog -stop-datetime =“2013-01-17 12:00:23”d:/binlog/mylog.000001 | mysq -uroot -p

(恢復到停止時間之前的所有數據)

Mysqlbinlog-start-datetime =“2013-01-17 12:00:23”d:/binlog/mylog.000001 | mysq -uroot -p

(恢復開始時間到之後的所有數據)

4,2按照位置恢復

  Mysqlbinlog-stop-position =“234”d:/binlog/mylog.000001 | mysq -uroot -p

(恢復到停止時間之前的所有數據)

Mysqlbinlog-start-position =“234”d:/binlog/mylog.000001 | mysq -uroot -p

(恢復開始時間到之後的所有數據)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章