關於SQL性能優化,求助!!!


關於SQL的性能優化,
具體從哪里開始着手?
根據我現在的sql文
1
  select count(*) 改成select count(字段1)
2
  select tableA.*之類的,改成select tableA.字段1,字段2。。。。。。
3
  from tableB,tableC 迪卡爾積的地方,根據表間關系,改成inner join

我想問問,具體通常還有那些需要注意的地方。
select from
tableA
left join tableB on
left join tableC on 
......


我想問一下,對於所要結果,tableB中的字段我並不是都想要,
select from
tableA 
left join (select 所需字段 from tableB) tableB on
......

這樣的寫法,那個性能好一些。


2 个解决方案

#1


范圍太廣了  我之前寫過一個東西,是給公司新人教育訓練用的  不知道對你有沒有幫助。

我知道寫的不怎么樣,(我可沒出來獻)各位大俠千萬不要罵我啊!!!   只是給樓主一點資料


  SELECT語句優化設計

1.數據庫查詢語句優化的重要性概述

優化概述

其實我們發現很多人只是需要從一個數據庫中檢索出信息。這些人的數量比從事數據庫編程和應用的人要多的多。而且數據查詢的效率直接影響軟件的效率和企業的運營。SQL語句是在程序開發階段就已經決定了的由於低效率的SQL語句給數據庫性能帶來的問題,往往在數據庫運行一段時間后才凸現出來,但發現后就變的難以改變,成為不可突破的性能瓶頸。
因為幾乎所有數據庫都不可避免的運行一些效率低下的SQL語句。對數據庫性能的調整,往往是從SQL語句優化開始。                                          
SQL語句的優化可以使數據庫減少負荷,提高使用效率 ,相對於硬件升級是比較經濟的一種方法。

優化規則

絕大多數情況下,我們並不需要去關心SQL語句是怎么執行的,這是因為當前流行的數據庫軟件中都無一例外的采用了高性能的優化器,而這些優化器在絕大多數的情況下都能將用戶某些不合理的SQL語句結構轉換成更合理的形式,從而有效的提高SQL的執行效率。
優化器的優化原則有兩種:
1.成本的優化:對一條SQL語句,優化器會生成所有可能的執行方式,估計這些執行方式將使用的硬件成本,相互比較之后從中選擇成本最低的執行計划。缺點是必須收集大量統計數據,給服務器造成額外的負擔。


2.基於規則的優化:相對於上面的優化原則,規則優化顯得死板的多。它只是根據預先設計好的規則進行運算,我們知道在現實生活中,預先設計好的規則有時候都是很沒效率。

#2


2。SELECT優化方法

討論關鍵字
SELECT這個關鍵字沒什么好討論的,主要就是與其組合的關鍵字下面我們來一一討論:

FROM
該關鍵字后面跟表名,當然可以跟多個,但只要條件設置的好就沒有問題。如:SELECT AID,BID FROM A,B WHERE AID=BID  這樣設置的話就沒有問題,數據庫會先通過條件建立AB表的邏輯表然后進行查找需要的數據。但是值得注意的是,如果這兩表沒有建立索引那么就有點麻煩了,因為數據庫會進行全表掃描,在數據量比較大的情況下這是我們所不希望看到的,那么有沒有辦法解決呢?當然,設置聚集索引,就像在看一本書,如果我們沒有目錄,我們只能從第一頁行查找,這和數據庫是一個道理。

索引
總的來說索引可以分為聚集索引和非聚集索引。一個表中只能有一個聚集索引。對一個表建立一個聚集索引后,數據庫會調整記錄的順序,使表按照索引的順序重新排列。而非聚集索引不會改變表的順序。
建立索引的幾種情況有:
1.主鍵列、經常有范圍查找和ORDER BY或GROUP BY的列,可以考慮建立聚集索引;
2.在使用頻繁的列且經常需要使用函數的時候,可以考慮使用函數索引。
3.外鍵列、頻繁修改更新的列,可以考慮使用非聚集索引。
   索引雖有助於提高性能,但並不是索引越多越好,恰好相反過多的索引會導致系統低效。因為用戶在沒一個表中每增加一個索引,維護索引集合就要做相應的更新工作,同時每次有數據改變的時候就需要維護索引。

WHERE
該條件語句雖然簡單,但不同的使用方法結果卻截然不同。比如:
select * from table1 where name= ’zhangsan’ and TID > 10000
與 select * from table1 where TID > 10000 and name= ’zhangsan’ 
一些人不知道以上兩條語句的執行效率是否一樣,因為如果簡單的從語句先后上看,這兩個語句的確是一樣的,但如果TID是一個聚合索引,那么后一句僅僅從表的10000條以后的記錄中查找就行了;而前一句則要先從全表中查找看有幾個name='zhangsan'的,而后再根據限制條件條件tID>10000來提出查詢結果。如果在記錄集較多的情況下區別是非常大的。
但有時你會發現着兩句的效率其實差不多。這是什么原因呢?因為絕大多數數據庫軟件中有一個“查詢分析優化器”,它可以計算出where子句中的搜索條件並確定哪個索引能縮小表掃描的搜索空間,也就是說,它能實現自動優化。但是也必須付出代價,就是數據庫軟件會消耗一部分開銷去優化低效的SQL語句。如果你的SQL語句寫的比較復雜的話,那么軟件在比對與分析SQL語句上的開銷是很大的。

盡量減少格式轉換
舉個簡單的例子:某表有一時間字段,現在需要與‘20050101’和‘20051231’進行比較。我們比較下面兩個語句:(PGSQL)
SELECT * FROM TABLE1 WHERE TO_CHAR(WORKDATE,’YYYMMDD’) BETWEEN ‘20050101’ AND ‘20051231’  將WORKDATE轉換成字符串進行比較。

SELECT * FROM TABLE1 WHERE 
WORKDATE>=TO_DATE(‘2005-01-01’,’YYYY-MM-DD’)  AND
WORKDATE<=TO_DATE(‘2005-12-31’,’YYYY-MM-DD’) 將字符串轉換成日期型進行比較。
第二句SQL的性能明顯優於第一句。這是因為第一句數據庫必須將沒一行記錄的日期都轉換一次,而第二句只需要對常量做轉換。(以上結論成立的前提是日期字段不能使用索引)

    謹慎使用IS NULL 和 IS NOT NULL
不能用NULL做索引,任何包含NULL值的列都將不會被包含在索引中。即使在列上建立索引,只要這些列中含有NULL,該列就會從索引中刪除。也就是說,如果某列存在空值,即使對該列建索引也不會提高性能。同時,任何在WHERE子句中使用IS NULL或者IS NOT NULL優化器是不允許使用索引的。

IN和OR
SQLSERVER會自動將IN轉換成OR,因此對SQLSERVER來說下面兩句是一樣的。SELECT ID FROM USERS WHERE ID = ‘1’OR ID = ‘2’OR ID = ‘3’這句查找出ID是1或2或3的人。

SELECT ID FEOM USERS WHERE ID IN(1,2,3)的效率是一樣的。
而對於其他數據庫來說,大多數參考書都說IN的效率比OR高。
    
    ORDER BY
對於ORDER BY是非常重要的關鍵子,我們不希望數據是雜亂無章的,那樣對我們沒有價值,而該關鍵子使我們可以得到想要的結果。但是也必須付出代價,消耗一定的資源。當然如果在需要經常排序的列上建立索引的話是有助於提高查詢性能的。(注意:過多的索引反而影響系統速度)

    GROUP BY
在使用統計函數時要用到它,同樣的也回消耗資源,但是為了得到結果也是必須的。和排序一樣,如果在某列建立了索引的是話,那么將會有助於提高查詢效率。(注意:過多的索引反而影響系統速度)




    帶通配符(%)的LIKE 語句
要求在表中查詢出包含‘A’的人。可以采用如下的查詢語句:SELECT * FROM TABLEA WHERE NAME LIKE ‘%A%’;這里由於通配符%在搜尋首出現,所以即使NAME建立了索引,有些數據庫也將不使用NAME的索引。在很多情況下可能是無法避免的,但是要做到心中有低,通配符如此使用會降低查詢速度。
當然通配符出現在字符串其他位置時,優化器可以利用索引。如:SELECT * FROM TABLEA WHERE NAME LIKE ‘A%’;

查詢字段需要多少,查詢多少
我們每少提取一個字段,查詢速度就會有相應的上升。所以要避免SELECT *這樣的查詢出現,需要哪些字段就查哪些字段。

關鍵字DISTINCT
取消重復值也許會在很多SQL語句中出現,但是筆者的感覺是盡量不要多用。在實際應用中發現有時數據庫出現了多筆重復的問題,但被該關鍵字給掩蓋了。或者有時候查詢出很多重復的數據,有些人也許會用該關鍵字來解決着一問題。但是,我覺得重復數據的出現肯定是有原因的,如果盲目使用這種方式去解決將遺留下很多問題。所以我的觀點是:該關鍵字要用,是在數據重復原因明確的情況下使用。這樣才能保證問題不會被掩蓋,保證數據庫運行一段時間以后不會出現難以彌補的問題。
一個小技巧,去除重復值還有另外一個方法。GROUP BY依據指定的分組列對所有行進行分組,而且每一組返回一個行。這與DISTINCT得到的結果相同。那么哪一種方法更好呢?其實DISTINCT是一個更容易理解的語句,而使用GROUP BY則可以使數據庫系統能更快地解決問題。

關於嵌套子查詢
有時候普通查詢對我們來說是脆弱的,多表或者更多表的時候往往需要其他的一些辦法,先不討論外連接。和絕大多數本本一樣,我建議不要輕易使用嵌套子查詢。原因很簡單,消耗效率。用SQLSERVER2000測試后發現兩表之間用其他的查詢方式,其效率是差不多的。但是如果使用了字查詢,那么他的成本消耗將會成倍的增長。如:SELECT AID,BID,BNAME FROM A,B WHERE A.AID=B.BID;原來兩表的效率是A+B。
如果使用了字查詢沒增加一個字段乘數就會加1,如:SELECT AID,(SELECT BID FROM B WHERE A.AID=B.BID),(SELECT BNAME FROM B WHERE A.AID=B.BID) FROM A;那么他的效率就是A+2*B。完成同樣的目的卻有截然不同的結果,所以請慎用嵌套子查詢。
上面一個例子也許有些牽強,因為沒有人會用第二種方法,但是我想突出的是如果是多表查詢的話,也要注意能不用盡量不用。(多表可以考慮使用外連接)

外連接內連接
根據性能測試發現內連接的性能高於外連接。如下兩句語句:select * from abm1008,abm1009,tbl_headmaterial where abm1008.abmfldid=abm1009.abmfldid and fld_abm8097=material_no(內連接)①

select * from abm1008 
left join (select * from abm1009 ) as abm1009 on abm1008.abmfldid=abm1009.abmfldid
 left join (select * from tbl_headmaterial) as tbl_headmaterial on abm1009.fld_abm8097=tbl_headmaterial.material_no(外連接)②
完成相同的任務只有一點差異,但是內連接的效率明顯要於外連接。
配置P42.4G  512M內存測試結果:
300次運行平均數據 ① ②
  客戶端處理累計時間   4.6087ms 42.5085ms
  服務器應答累計等待時間 465.85ms 629.678ms
CPU消耗 24 78
I/O消耗 112 122

    但是有時候不得已還是會使用外連接,所以要看情況,能使用內連接不使用外連接,如果一定要,就選擇表比較小的而且最好有建立索引的進行連接。


3.小結
本章主要講述查詢的優化,無論您的數據庫軟件優化器是否強大,這都是需要的。在您的數據庫運行速度不理想但有無法優化的情況下,這個是最節約成本的方法之一。
學習任何東西要去教條的學習,絕不能生搬硬套。要使用索引,但要考慮是否值得?過多的索引只會是數據庫負擔更大。用多少,什么時候用,關鍵看各位在實際工作中的經驗累計。根據現實狀況來選擇查詢語句的優化程度才是正確的方法。
    

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



關於SQL優化問題,求助!! 性能優化系列七:SQL優化 SQL之性能優化 SQL Server性能優化 SQL Server性能優化 SQL 性能優化 總結 SQL性能優化總結 ORACLE SQL性能優化三 性能優化——SQL語句 sql語句性能優化
 
粤ICP备14056181号  © 2014-2021 ITdaan.com