mysql優化

目前看網站的開發瓶頸

1. 帶寬-雲計算,雲終端(視屏網站)

2. 數據庫-網站大併發,海量存儲(sina,sohu )

 

話題 :怎樣做,我們的數據庫會更快!

 

數據庫分類:

關係型數據庫: mysqloraclesql serverdb2informix

非關係型數據面向集合,面向對象

nosql數據庫: mongodb PHP項目

 

 

數據庫優化應當考慮方面:

1. 數據庫的設計()->符號3NF(有時候反3NF)

2. select語句 ->重點(如何定位慢查詢)

3. 數據庫參數設置.

4. 配套硬件的設置(CPU、內存)

 

 

數據庫的設計

 

 

1.我們的數據表要滿足1NF, 含義是

表中的每條記錄是原子性約束 2. 只要數據庫是關係型數據庫,就滿足1NF

2.2NF 二範式

表中的記錄,不能夠出現完全一樣的記錄,就滿足了二範式,一般說是通過設置主鍵來完成.

3. 3NF, 三範式

表中的某個字段的信息,可以推導得出,不要出現冗餘數據.

比如下面就是不滿足3NF

  

 但是,規定是死的,技術是需要靈活使用.

sql語句的優化-針對Mysql

1. 通過 show status 可以查看當前Mysql的一些情況.

比如看看mysql一共執行了多少次 增,刪,改,查

show session  status like com_select【這個指令用於查看,當前會話,執行了多少次select

show session  status like com_update; //delete /insert

 

如果你希望查看的是數據庫從啓動到目前執行的情況則,命令應該這樣寫:

show global   status like com_update; //delete /inser

 

Connections:試圖連接MySQL服務器的次數

show status like Connections;
Uptime:服務器工作的時間(單位秒)
Slow_queries:慢查詢的次數 (默認是慢查詢時間10s) [重要的知識點如何找到慢查詢]


2. 在對mysqlselect 語句進行優化時,我們使用的工具是explain(具體說)

如何定位慢查詢

 

1.任務:做一張1800000 記錄的大表

使用的是自寫的腳本.(介紹Mysql的存儲過程和自定義函數)

<?php

$con=mysql_connect();

if(!$con){

exit;

}

//msql_select_db(temp,$con);

$sql=select  temp.rand_string();

 

?>

 查詢的慢日誌,默認是放在 my.ini文件 :

datadir="C:/Documents and Settings/All Users/Application Data/MySQL/MySQL Server 5.5/Data/"

 

2. 如果在工作中,需要去記錄慢查詢,則我們啓動mysql的方式是這樣

dos>bin\mysqld.exe  --slow-query-log

 

 

3. 用一個指令可以查看當前慢查詢的時間 ,默認10s

show variables like slow_query_time;

如果 測試,我們可以把這個默認的慢查詢時間10s->1s

set long_query_time=1;

 

4. 當你的查詢時間查過了1s ,則在

datadir="C:/Documents and Settings/All Users/Application Data/MySQL/MySQL Server 5.5/Data/"

就有日誌文件itcast-211b4ff3-slow.log

就記錄了.

 

Explain 的使用

基本用法是

explain sql語句;

 

作用是:通過explain 可以看到Mysql數據庫將怎樣執行你的sql語句


extra表示額外信息 (比如 where , filesort ,temp表)

rows: 修改一下說法(圖上有點錯誤): 估算出結果集行數

 

 

 我們使用子查詢時,會創建臨時表臨時表的效率相對比較低我們建議使用 left join 來完成完成查詢.

 

舉例

//查詢辦公地點在北京的 所有僱員

explain select * from emp where emp.deptno=(select * from dept where loc=bj);

 

select * from 1 left join 2 on 連接條件 where 更多條件

 

 

更詳細的說明

 

Explain select * from emp where ename=zrlcHd
會產生如下信息:
select_type:表示查詢的類型。
table:輸出結果集的表
type:表示表的連接類型
possible_keys:表示查詢時,可能使用的索引
key:表示實際使用的索引
key_len:索引字段的長度
rows:掃描的行數
Extra:執行情況的描述和說明

 

 

如何給表提速

 

MyISAM數據表,有三個文件, *.frm , *.myd , *.myi 

創建索引:

基本語法:

create index 索引名 on 表名(字段);

 

實際案例:

create index myind1 on emp(ename);

哪些字段不要建立索引

1. 唯一性差的字段不要建立索引 [sex ]

2. 變化頻繁的字段不要建立索引 [用戶在線狀態] [update]

3. where條件中,很少出現的不要建立索引.

4. where條件中經常出現,同時不滿足上面3個條件就應當建立索引.

 

 

索引的分類

1. 主鍵索引(只有這個字段,被設置成主鍵,則自動成爲主鍵索引在一張中只能有一個主鍵索引) primary key 是可以多個列構造.

2. 唯一索引(UNIQUE)

 

 create table bbb( id int primary key auto_increment, name varchar(20) unique);

insert into aaa values(1,aa);

insert into aaa values(1,bb); (x)

insert into aaa values(null,cc);

insert into aaa values(2,aa);(x)

insert into aaa values(3,null);

insert into aaa values(4,null);

 

 主鍵和UNIQUE的比較

① 主鍵不能重複,也不能爲NULL

② UNIQUE不能重複,但是可以爲NULL

 

3. 普通索引

4. 全文索引(FULLTEXT). ->MySql  -sphinx (中文分詞)/ coreseek

create fulltext index on news (content)

select * from news where content like 大暴雨%

 

創建索引

1. 主鍵索引創建

創建表的時候,就指定主鍵

create table aaa100(id int primary key ,name varchar(20) );

如果是複合主鍵

create table aaa100(id int ,name varchar(20), primary key (id,name) );

 

如果表已經創建好,然後通過修改的方法來添加主鍵索引.

 

ALTER TABLE emp ADD PRIMARY KEY (empno);

 

2. 唯一索引的創建

create unique index 索引名 on 表名(字段名);

 

3. 普通索引

create  index 索引名 on 表名(字段名);

 

4. 全文索引

create fulltext index 索引名 on 表名(字段名);

 

查詢索引

三種方法:

show index form 表名

show keys from 表名

desc 表名

 

修改索引

alter 。。

刪除索引,重新創建

 

刪除索引

drop index 索引名 on 表名 

alter table 表名 drop index索引名;

刪除主鍵索引

alter table 表名 drop primary key;

 

如何正確使用索引,和注意事項

 

1. 如果你創建的索引是複合索引:

alter table dept add index myind (dname,loc);

 

 那麼當select 語句用到左邊的列時,纔用到該索引.

 

2. 在使用like語句查詢時,當 like %aa 就不能使用到索引了

 

3. select 語句,儘量不要使用or 語句,因爲這個關鍵字,會讓索引失效.(比如 where 條件中有三個 字端有兩個是索引字段,但是有一個不是索引,導致一個索引都不要.)

 

4. 一會說意思建議 在mysql不管這個字段是數值,還是字符串,建議大家 使用’’引用一下.

 

5. 如果mysql發現掃描全部表,比通過索引查詢還快,就會不使用索引

 

 

 

小技巧

 

關於group by的優化

如果只希望分組,但不希望排序可以使用 order by null 來禁用排序

explain select *from dept group by loc order by null\G

 

 

有些情況下,可以使用連接來替代子查詢。(在實際開發中,使用left join 來替代案例到時在想),因爲使用joinMySQL不需要在內存中創建臨時表。(講解)

 

 

MyISAMINNODB的選擇

如果我們查詢某張表頻繁,同時對該表不需要太多的事務處理,則考試使用MyISAM

如果對某表操作是,對事務要求高,則使用INNODB

事務(1. commit 2. rollback, 3 savepoint)

 

MyISAM>INNODB

 

一個項目中,可以更加實際情況來決定,表使用什麼存儲引擎.

 

關於字段類型選擇

 

對應數值精度要求高的 建議使用 deciaml ,不要使用float

 

對應存儲引擎是MyISAM類型的,我們要定時對它優化. *.MYD

optimize table 表名 [優化]

 

日期類型要根據實際需要選擇能夠滿足應用的最小存儲的早期類型

 

這裏說明一下datetime   timestamp區別:

timestamp 是會跟着你的update變化的.

我建議大家 關於時間字段,可以使用 datetime , 也可以使用int

 

提出一個: 如果取出 一個小時內的新貼.

 

time()-3600*30

 

mysql函數-DEDE [日期函數]

 

補充: datetime 這樣就可以使用Mysql數據庫提供的日期函數.

 

 

create table bbs(id int primary key, poster varchar(32), content varchar(1024),posttime datetime);

 

//請查詢1個小時內,發的最新帖子

 

最重要的函數是 DATE_ADD(時間,間隔時間); | DATE_SBU

select * from bbs where DATE_ADD(now(),interval  -1 hour) < posttime;  

 表的水平劃分

所謂表的水平分割,指的是:把一張大表,根據某個標準(實際來定),分割成小表,各個表的結構都是一樣的! (關鍵點是,找到分割表的標準

 表的垂直分割

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