Sql語句總結及sql的優化

(個人學習專用,勿擾)
1、查詢指定列
例如: SELECT cid,cname
FROM student

2、消除重複元素,使用 DISTINCT關鍵字
例如: SELECT DISTINCT name
FROM student
(消除相同的name)

3、查詢年齡大於或等於19歲的同學學號、姓名、出生日期
select sno,sname,birthday
from student
where year(getdate())-year(birthday)>=19

(函數getdate()可獲取當前系統的日期,year()用於提取日期中的年份)

4、範圍查詢
between…and 可用於查詢屬性值在某一範圍內的元組
not between…and 可用於查詢不在某一範圍內的元組
例子,
select sno,score
from score
where score between 80 and 90

5、集合查詢
in 可用於查詢屬性值在某個集合內的元組
not in 可用於查詢屬性值不在某個集合內的元組
例如,
在Score表中查詢選修了001,005或003課程的同學學號、課程號和相應成績
select sno,cno,score
from Score
where cno in(‘001’,’005’.’003’)

6、聚合查詢
count({* | <列名>}) :統計關係的元組個數或一列中值的個數
sum(<列名>) : 統計一列中值的總和(必須爲數值型)
avg(<列名>) : 統計一列中值的平均值(必須爲數值型)
max(<列名>) : 統計一列中值的最大值
min(<列名>) : 統計一列中值的最小值

7、分組聚合
group by子句對查詢結果按某一列或幾列進行分組,值相等的分爲一組;
having 子句對分組的結果進行選擇,僅輸出滿足條件的組

例子:
a、查詢每個同學的選課門數、平均分、最高分
select sno,count(*) 門數,avg(score) 平均分,
max(score) 最高分
from Score
group by sno

(該查詢結果按學號sno進行分組,將具有相同sno的值的元組作爲一組,然後對魅族進行相應的計數,求平均值,最大值)

b、查詢平均分在80分以上的每個同學的選課門數、平均分、最高分
select sno,count(*) 門數,avg(score) 平均分,
max(score) 最高分
from Score
group by sno
having avg(score)>=80

8、case when例子
student表

在這裏插入圖片描述
score表
在這裏插入圖片描述
在這裏插入圖片描述

索引
唯一索引
ALTER TABLE table_name ADD UNIQUE (column);創建唯一索引
普通索引
ALTER TABLE table_name ADD INDEX index_name (column);創建普通索引
組合索引
ALTER TABLE table_name ADD INDEX index_name(column1, column2, column3);創建組合索引
全文索引
ALTER TABLE table_name ADD FULLTEXT (column);創建全文索引

Mysql的優化
Mysql的優化,大體可以分爲三部分:索引的優化,sql語句的優化,表的優化

1.索引的優化
只要列中含有NULL值,就最好不要在此例設置索引,複合索引如果有NULL值,此列在使用時也不會使用索引
儘量使用短索引,如果可以,應該制定一個前綴長度
對於經常在where子句使用的列,最好設置索引,這樣會加快查找速度
對於有多個列where或者order by子句的,應該建立複合索引
對於like語句,以%或者‘-’開頭的不會使用索引,以%結尾會使用索引
儘量不要在列上進行運算(函數操作和表達式操作)
儘量不要使用not in和<>操作

2.sql語句的優化
查詢時,能不要就不用,儘量寫全字段名
大部分情況連接效率遠大於子查詢
多使用explain和profile分析查詢語句
查看慢查詢日誌,找出執行時間長的sql語句優化
多表連接時,儘量小表驅動大表,即小表 join 大表
在千萬級分頁時使用limit
對於經常使用的查詢,可以開啓緩存

3.表的優化
表的字段儘可能用NOT NULL
字段長度固定的表查詢會更快
把數據庫的大表按時間或一些標誌分成小表
將表分區

sql優化
1、對查詢進行優化,應儘量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。

2、應儘量避免在 where 子句中對字段進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:
select id from t where num is null
可以在num上設置默認值0,確保表中num列沒有null值,然後這樣查詢:
select id from t where num=0

3、應儘量避免在 where 子句中使用!=或<>操作符,否則將導致引擎放棄使用索引而進行全表掃描。

4、應儘量避免在 where 子句中使用 or 來連接條件,否則將導致引擎放棄使用索引而進行全表掃描,如:
select id from t where num=10 or num=20
可以這樣查詢:
select id from t where num=10
union all
select id from t where num=20

5、in 和 not in 也要慎用,否則會導致全表掃描,如:
select id from t where num in(1,2,3)
對於連續的數值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3

6、下面的查詢也將導致全表掃描:
select id from t where name like ‘%abc%’

7、應儘量避免在 where 子句中對字段進行表達式操作,這將導致引擎放棄使用索引而進行全表掃描。如:
select id from t where num/2=100
應改爲:
select id from t where num=100*2

8、應儘量避免在where子句中對字段進行函數操作,這將導致引擎放棄使用索引而進行全表掃描。如:
select id from t where substring(name,1,3)=‘abc’–name以abc開頭的id
應改爲:
select id from t where name like ‘abc%’

9、不要在 where 子句中的“=”左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引。

10、在使用索引字段作爲條件時,如果該索引是複合索引,那麼必須使用到該索引中的第一個字段作爲條件時才能保證系統使用該索引,否則該索引將不會被使用,並且應儘可能的讓字段順序與索引順序相一致。

11、不要寫一些沒有意義的查詢,如需要生成一個空表結構:
select col1,col2 into #t from t where 1=0
這類代碼不會返回任何結果集,但是會消耗系統資源的,應改成這樣:
create table #t(…)

12、很多時候用 exists 代替 in 是一個好的選擇:
select num from a where num in(select num from b)
用下面的語句替換:
select num from a where exists(select 1 from b where num=a.num)

13、並不是所有索引對查詢都有效,SQL是根據表中數據來進行查詢優化的,當索引列有大量數據重複時,SQL查詢可能不會去利用索引,如一表中有字段sex,male、female幾乎各一半,那麼即使在sex上建了索引也對查詢效率起不了作用。

14、索引並不是越多越好,索引固然可以提高相應的 select 的效率,但同時也降低了 insert 及 update 的效率,
因爲 insert 或 update 時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。
一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有必要。

15、儘量使用數字型字段,若只含數值信息的字段儘量不要設計爲字符型,這會降低查詢和連接的性能,並會增加存儲開銷。
這是因爲引擎在處理查詢和連接時會逐個比較字符串中每一個字符,而對於數字型而言只需要比較一次就夠了。

16、儘可能的使用 varchar 代替 char ,因爲首先變長字段存儲空間小,可以節省存儲空間,
其次對於查詢來說,在一個相對較小的字段內搜索效率顯然要高些。

17、任何地方都不要使用 select * from t ,用具體的字段列表代替“*”,不要返回用不到的任何字段。

18、避免頻繁創建和刪除臨時表,以減少系統表資源的消耗。

19、臨時表並不是不可使用,適當地使用它們可以使某些例程更有效,例如,當需要重複引用大型表或常用表中的某個數據集時。但是,對於一次性事件,最好使用導出表。

20、在新建臨時表時,如果一次性插入數據量很大,那麼可以使用 select into 代替 create table,避免造成大量 log ,
以提高速度;如果數據量不大,爲了緩和系統表的資源,應先create table,然後insert。

21、如果使用到了臨時表,在存儲過程的最後務必將所有的臨時表顯式刪除,先 truncate table ,然後 drop table ,這樣可以避免系統表的較長時間鎖定。

22、儘量避免使用遊標,因爲遊標的效率較差,如果遊標操作的數據超過1萬行,那麼就應該考慮改寫。

23、使用基於遊標的方法或臨時表方法之前,應先尋找基於集的解決方案來解決問題,基於集的方法通常更有效。

24、與臨時表一樣,遊標並不是不可使用。對小型數據集使用 FAST_FORWARD 遊標通常要優於其他逐行處理方法,尤其是在必須引用幾個表才能獲得所需的數據時。
在結果集中包括“合計”的例程通常要比使用遊標執行的速度快。如果開發時間允許,基於遊標的方法和基於集的方法都可以嘗試一下,看哪一種方法的效果更好。

25、儘量避免大事務操作,提高系統併發能力。

26、儘量避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理。

發佈了20 篇原創文章 · 獲贊 30 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章