Mysql sql語句技巧與優化
一、常見sql技巧
1、正則表達式的使用
2、巧用RAND()提取隨機行
mysql數據庫中有一個隨機函數rand()是獲取一個0-1之間的數,利用這個函數和order by一起能夠吧數據隨機排序,
、 mysql>select * from stu order by rand();
下面是通過limit隨機抽取了3條數據樣本。
mysql>select * from stu order by rand() limit 3;
3、利用GROUP BY 的WITH ROLLUP子句統計
使用group by的with rollup子句可以檢索出更多的聚合信息。
mysql>select cname,pname,count(pname) from demo group by cname,pname;
同樣使用with rollup關鍵字後,統計出更多的信息。注意:with rollup不可以和order by同時使用。
mysql>select cname,pname,count(pname) from demo group by cname,pname with rollup;
4、用BIT GROUP FUNCTIONS 做統計
在使用group by語句時可以同時使用bit_anf、bit_or函數來完成統計工作,這兩個函數的主要作用是做數值之間的邏輯位運算。
mysql>select id,bit_or(kind) from order_rab group by id; //二進制位運算
對order_rab表中id分組時對kind做位與和或計算。
mysql>select id,bit_and(kind) from order_rab group by id; //二進制餘運算,只有11才爲1
5、使用外健要注意的問題
創建外健如下:
mysql>create table temp(id int,name char(20),foreign key(id) references outTable(id) on delete cascade on update cascade));
注意:innodb類型的表支持外健,myisam類型的表,雖然創建可以成功,但不起作用,主要原因是不支持外健。
6、mysql中help的使用
a、?%可以獲得所有mysql>裏的命令,
b、?create
c、?opt%,因爲記不住全稱。
二、mysql的優化
1、優化sql語句的一般步驟
通過show status命令瞭解各種sql的執行頻率。
格式:mysql>show [session|global] status;
session:(默認)表示當前鏈接
globla:表示自數據庫啓用至今
如:mysql>show status;
mysql>show global status;
mysql>show status like "Com_%";
mysql>show global status like "Com_%";
參數說明:
Com_select 執行select操作的次數,一次查詢值累計加1
Com_update 執行update操作的次數
Com_insert 執行insert操作的次數
Com_delete 執行delete操作的次數
只針對Innodb引擎的:
InnoDB_rows_read執行select操作的次數
InnoDB_rows_update執行update操作的次數
InnoDB_rows_insert執行insert操作的次數
InnoDB_rows_delete執行delete操作的次數
其他:
connections鏈接mysql的數量
Uptime服務器已經工作的秒數
Slow_queries慢查詢的次數
2、定位執行效率較低的sql語句:
a、explain select * from table where id = 1000;
b、desc select * from table where id = 1000;
c、優化的順序:
1)查看慢查詢日誌,日誌裏查詢超過10秒的說明產尋幽問題
2)通過desc定位這條語句哪裏有問題。
3)通過方案對問題點進行優化,如加索引
2、索引問題
索引實數據庫優化中最常見的也是最重要的手段之一,通過索引通常可以幫助用戶姐絕大多數的sql性能問題。
1)索引的存儲和分類:
MyISAM存儲引擎的表的數據和索引是自動分開存儲的,各自是獨一的一個文件;InnoBDB存儲引擎的表的數據和索引是存儲在同一個表空間裏面,但可以由多個文件組成。
mysql目前不支持函數索引,但是能對列的前面某一部分進行進行索引,例如name字段,可以去name的前2個字符進行索引,這個特性可以大大縮小文件的大小,用戶在設計表結構的時候也可以對文本列根據此特性進行靈活設計。
mysql>create index ind_company2_name on company2(name(4));//company表名,ind_company2_name索引名
2)mysql如何使用索引
索引用於快速找出在某個列中有一特定值的行。對相關列使用索引是提高SELECT操作性能的最佳途徑。
a、使用索引
(1)對於創建的多行索引,只要查詢的條件中用到最左邊的列,索引一般就會被使用。如下創建一個複合索引。
mysql>create index ind_sales2_com_mon onsales2(company_id,moneys);
然後按company_id進行查詢,發現使用到了複合索引。
mysql>explain select * from sales2 where company_id=2006\G;
使用下面的查詢就沒有使用複合索引。
mysql>explain select * from sales2 where moneys=1\G;
(2)使用like的查詢,後面如果是常量並且只有%號不在第一個字符,索引纔可能被使用,如下:
mysql>explan select * from company2 where name like "%3"\G;
3)存在索引但不使用索引
(1)如果mysql估計使用索引比全表掃描更慢,則不使用索引。例如如果列key_prat1均勻分佈在1-100之間,查詢時使用索引就不是很好
mysql>select * from table_name where ley_part1>1 and key_part<90;
(2)如果使用MEMORY/HEAP表並且where條件中不使用“=”進行索引列,那麼不會用到索引。Heap表只有在“=”的條件下使用索引。
(3)用or分割的條件,如果or前的條件中的列有索引,二後面的列沒有索引,那麼涉及的索引都不會用到。
(4)如果不是索引列的第一部分,如下例子:可見雖然在money上面建有複合索引,但是由於money不是索引的第一列,那麼在查詢中,這個索引也不會被mysql採用。
mysql>explan select * from sales2 where moneys=1\G;
(5)如果like是一%開始,可見雖然在name上家有索引,但是由於條件中的like的值的“%”在第一位了,那麼mysql也不會採用這個索引。
(6)如果列類型是字符串,但在查詢時把第一個數值型常量賦值給了一個字符類型的列名name,那麼雖然在name列上有索引,但是也沒有用到。
mysql>explain select * from company2 where name=294\G;
4)查看索引的使用情況
如果索引正在工作,Handler_read_key的值將很高,這個值代了一個行別索引值讀的次數。
Handler_read_next的高則意味着查詢運行低效,並且應該建立索引補救。
3、兩個簡單的優化方法
對於多數開發人員來說,可能希望掌握一些簡單實用的優化方法,對於更堵更復雜的優化,更傾向於交給作業dba來做。
1)定期分析表和檢查表
ANALYZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tal_name[,tbl_name]....
本語句用於分析和儲存表的關鍵字分佈,分析的結果將可以得到準確的統計信息,使得sql能夠生成正確的行計劃。
2)定期優化表
4、常用sql的優化
1)大批量插入數據。
當用load命令導入數據庫的時候,適當設置可以提高導入速度。
對於myisam存儲引擎的表,可以通過以下方式快速的導入大量的數據。
ALTER TABLE tbl_name DISABLE KEYS
loading the data
ALTER TABLE tbl_name ENABLE KEYS
DISABLE KEYS和ENABLE KEYS用來打開或關閉mysiam表非唯一索引的更新,可以提高速度。注意:對innodb表無效。
2)關閉唯一性校驗可以提高導入效率。
再倒入數據前限制性set unique_checks=0,關閉唯一性校驗,再倒入結束後執行set unique_checks=1,恢復唯一性校驗可以提高到付效率。
3)優化insert語句
及兩使用多個值表的insert語句,這樣可以大大算短客戶與數據庫的連接、關閉等損耗。
可以使用insert delayed(馬上執行)語句得到更高的效率將索引文件和數據文件分別存放不同的磁盤上。
可以增加bulk_buffer_size變量值的方法來提高速度,但是隻對myisam表使用。
當一個文件裝載一個表時,使用LOAD DATA INFILE。這個通常比使用很多insert語句要快20唄。
4)優化group bu語句
如果查詢包含group by但用戶想要避免排序結果的損耗,則可以使用order by null來禁止排序:
如下沒有使用order by null 來禁止排序。
5)優化order by語句
在某些情況中,mysql可以使用一個索引來滿足order by 子句,而不需要額外的排序。where條件和order by使用相同的索引,並且order by的順序和索引順序相同,並且order by的字段都是升序或者降序。
6)優化嵌套查詢
下面是採用嵌套查詢的效果(可以使用更有效的鏈接查詢(join)替代)
explain select * from sales2 where company_id not in (select id from complany2)\G