Ⅰ 如何進行sql性能優化
這里分享下mysql優化的幾種方法。
1、首先在打開的軟體中,需要分別為每一個表創建 InnoDB FILE的文件。
Ⅱ sql效率優化通過索引
要看索引欄位的順序
如果a+b+c是唯一索引,那麼建再a+b索引,只會減慢修改表時的效率,對查詢沒有幫助。
如果建的是b+c或是c,而且查詢條件中也就只有b和c就有可能提高效率。
只要記得索引中欄位是有順序的,查詢時的條件如果沒有索引的第一個欄位,則不會再使用索引。
當然,SQL使不使用索引也跟表的行大小、數據量的實際大小以及重復數據的分布情況有關系,如果sqlserver分析出來掃描全表所需的時間比使用索引還快的話,就不會再使用索引了。
Ⅲ 怎樣進行sql資料庫的優化
1、資料庫空間是個概述,在sqlserver里,使用語句 exec sp_spaceused 'TableName' 這個語句來查。
Ⅳ 如何優化SQL
(1)選擇最有效率的表名順序(只在基於規則的優化器中有效): ORACLE的解析器按照從右到左的順序處理FROM子句中的表名,FROM子句中寫在最後的表(基礎表 driving table)將被最先處理,在FROM子句中包含多個表的情況下,你必須選擇記錄條數最少的表作為基礎表。如果有3個以上的表連接查詢, 那就需要選擇交叉表(intersection table)作為基礎表, 交叉表是指那個被其他表所引用的表. (2) WHERE子句中的連接順序.: ORACLE採用自下而上的順序解析WHERE子句,根據這個原理,表之間的連接必須寫在其他WHERE條件之前, 那些可以過濾掉最大數量記錄的條件必須寫在WHERE子句的末尾. (3) SELECT子句中避免使用『 * 『: ORACLE在解析的過程中, 會將'*' 依次轉換成所有的列名, 這個工作是通過查詢數據字典完成的, 這意味著將耗費更多的時間 (4)減少訪問資料庫的次數: ORACLE在內部執行了許多工作: 解析SQL語句, 估算索引的利用率, 綁定變數 , 讀數據塊等; (5)在SQL*Plus , SQL*Forms和Pro*C中重新設置ARRAYSIZE參數, 可以增加每次資料庫訪問的檢索數據量 ,建議值為200 (6)使用DECODE函數來減少處理時間: 使用DECODE函數可以避免重復掃描相同記錄或重復連接相同的表. (7)整合簡單,無關聯的資料庫訪問: 如果你有幾個簡單的資料庫查詢語句,你可以把它們整合到一個查詢中(即使它們之間沒有關系) (8)刪除重復記錄: 最高效的刪除重復記錄方法 ( 因為使用了ROWID)例子:DELETE FROM EMP E WHERE E.ROWID > (SELECT MIN(X.ROWID) FROM EMP X WHERE X.EMP_NO = E.EMP_NO); (9)用TRUNCATE替代DELETE: 當刪除表中的記錄時,在通常情況下, 回滾段(rollback segments ) 用來存放可以被恢復的信息. 如果你沒有COMMIT事務,ORACLE會將數據恢復到刪除之前的狀態(准確地說是恢復到執行刪除命令之前的狀況) 而當運用TRUNCATE時, 回滾段不再存放任何可被恢復的信息.當命令運行後,數據不能被恢復.因此很少的資源被調用,執行時間也會很短. (譯者按: TRUNCATE只在刪除全表適用,TRUNCATE是DDL不是DML) (10)盡量多使用COMMIT: 只要有可能,在程序中盡量多使用COMMIT, 這樣程序的性能得到提高,需求也會因為COMMIT所釋放的資源而減少: COMMIT所釋放的資源: a. 回滾段上用於恢復數據的信息. b. 被程序語句獲得的鎖c. redo log buffer 中的空間d. ORACLE為管理上述3種資源中的內部花費 (11)用Where子句替換HAVING子句: 避免使用HAVING子句, HAVING 只會在檢索出所有記錄之後才對結果集進行過濾. 這個處理需要排序,總計等操作. 如果能通過WHERE子句限制記錄的數目,那就能減少這方面的開銷. (非oracle中)on、where、having這三個都可以加條件的子句中,on是最先執行,where次之,having最後,因為on是先把不符合條件的記錄過濾後才進行統計,它就可以減少中間運算要處理的數據,按理說應該速度是最快的,where也應該比having快點的,因為它過濾數據後才進行sum,在兩個表聯接時才用on的,所以在一個表的時候,就剩下where跟having比較了。在這單表查詢統計的情況下,如果要過濾的條件沒有涉及到要計算欄位,那它們的結果是一樣的,只是where可以使用rushmore技術,而having就不能,在速度上後者要慢如果要涉及到計算的欄位,就表示在沒計算之前,這個欄位的值是不確定的,根據上篇寫的工作流程,where的作用時間是在計算之前就完成的,而having就是在計算後才起作用的,所以在這種情況下,兩者的結果會不同。在多表聯接查詢時,on比where更早起作用。系統首先根據各個表之間的聯接條件,把多個表合成一個臨時表後,再由where進行過濾,然後再計算,計算完後再由having進行過濾。由此可見,要想過濾條件起到正確的作用,首先要明白這個條件應該在什麼時候起作用,然後再決定放在那裡 (12)減少對表的查詢: 在含有子查詢的SQL語句中,要特別注意減少對表的查詢.例子:SELECT TAB_NAME FROM TABLES WHERE (TAB_NAME,DB_VER) = ( SELECT TAB_NAME,DB_VER FROM TAB_COLUMNS WHERE VERSION = 604) (13)通過內部函數提高SQL效率.: 復雜的SQL往往犧牲了執行效率. 能夠掌握上面的運用函數解決問題的方法在實際工作中是非常有意義的 (14)使用表的別名(Alias): 當在SQL語句中連接多個表時, 請使用表的別名並把別名前綴於每個Column上.這樣一來,就可以減少解析的時間並減少那些由Column歧義引起的語法錯誤. (15)用EXISTS替代IN、用NOT EXISTS替代NOT IN: 在許多基於基礎表的查詢中,為了滿足一個條件,往往需要對另一個表進行聯接.在這種情況下, 使用EXISTS(或NOT EXISTS)通常將提高查詢的效率. 在子查詢中,NOT IN子句將執行一個內部的排序和合並. 無論在哪種情況下,NOT IN都是最低效的 (因為它對子查詢中的表執行了一個全表遍歷). 為了避免使用NOT IN ,我們可以把它改寫成外連接(Outer Joins)或NOT EXISTS. 例子:(高效)SELECT * FROM EMP (基礎表) WHERE EMPNO > 0 AND EXISTS (SELECT 『X' FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = 『MELB') (低效)SELECT * FROM EMP (基礎表) WHERE EMPNO > 0 AND DEPTNO IN(SELECT DEPTNO FROM DEPT WHERE LOC = 『MELB') (16)識別'低效執行'的SQL語句: 雖然目前各種關於SQL優化的圖形化工具層出不窮,但是寫出自己的SQL工具來解決問題始終是一個最好的方法:SELECT EXECUTIONS , DISK_READS, BUFFER_GETS, ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2) Hit_radio, ROUND(DISK_READS/EXECUTIONS,2) Reads_per_run, SQL_TEXT FROM V$SQLAREA WHERE EXECUTIONS>0 AND BUFFER_GETS > 0 AND (BUFFER_GETS-DISK_READS)/BUFFER_GETS < 0.8 ORDER BY 4 DESC; (17)用索引提高效率: 索引是表的一個概念部分,用來提高檢索數據的效率,ORACLE使用了一個復雜的自平衡B-tree結構. 通常,通過索引查詢數據比全表掃描要快. 當ORACLE找出執行查詢和Update語句的最佳路徑時, ORACLE優化器將使用索引. 同樣在聯結多個表時使用索引也可以提高效率. 另一個使用索引的好處是,它提供了主鍵(primary key)的唯一性驗證.。那些LONG或LONG RAW數據類型, 你可以索引幾乎所有的列. 通常, 在大型表中使用索引特別有效. 當然,你也會發現, 在掃描小表時,使用索引同樣能提高效率. 雖然使用索引能得到查詢效率的提高,但是我們也必須注意到它的代價. 索引需要空間來存儲,也需要定期維護。</SPAN>
Ⅳ 有哪些常見的資料庫優化方法
MRR 是 MySQL 針對特定查詢的一種優化手段。假設一個查詢有二級索引可用,讀完二級索引後要回表才能查到那些不在當前二級索引上的列值,由於二級索引上引用的主鍵值不一定是有序的,因此就有可能造成大量的隨機 IO,如果回表前把主鍵值給它排一下序,那麼在回表的時候就可以用順序 IO 取代原本的隨機 IO。
如果想關閉 MRR 優化的話,就要把優化器開關 mrr 設置為 off。
默認只有在優化器認為 MRR 可以帶來優化的情況下才會走 MRR,如果你想不管什麼時候能走 MRR 的都走 MRR 的話,你要把 mrr_cost_based 設置為 off,不過最好不要這么干,因為這確實是一個坑,MRR 不一定什麼時候都好,全表掃描有時候會更加快,如果在這種場景下走 MRR 就完成了。
MRR 要把主鍵排個序,這樣之後對磁碟的操作就是由順序讀代替之前的隨機讀。從資源的使用情況上來看就是讓 CPU 和內存多做點事,來換磁碟的順序讀。然而排序是需要內存的,這塊內存的大小就由參數 read_rnd_buffer_size 來控制。
Ⅵ oracle sql優化涉及哪些原理
B 樹索引(B-Tree索引)
B樹索引是我們在oracle資料庫中最常用的索引,在詳細介紹訪問方法之前,我們看一下B-TREE索引的結構(圖片來源網路)
oracle的B樹索引就好像一顆長到的樹,他包含兩種類型,一種是索引分支塊(根節點塊,分支節點塊)一種是索引葉子塊(葉子節點塊)。分節點用來搜索,葉子節點用來存儲數據。根節點存儲索引的低層分支節點的數據。 由於所有的葉子節點均會自動的存儲成相同的深度,所以稱為「平 衡樹索引」, 故此,從任何葉子處檢索數據消耗的時間都是相同的。
對於分支節點塊(包括根節點塊)來說,其所包含的索引條目都是按照順序排列的(預設是升序排列,也可以在創建索引時指定為降序排列)。每個索引條目(也可以叫做每條記錄)都具有兩個欄位。第一個欄位表示當前該分支節點塊下面所鏈接的索引塊中所包含的最小鍵值;第二個欄位為四個位元組,表示所鏈接的索引塊的地址,該地址指向下面一個索引塊。 比如從上圖一可以看到,對於根節點塊來說,包含三條記錄,分別為(0 B1)、(500 B2)、(1000 B3),它們指向三個分支節點塊。其中的0、500和1000分別表示這三個分支節點塊所鏈接的鍵值的最小值。而B1、B2和B3則表示所指向的三個分支節點塊的地址。在一個分支節點塊中 所能容納的記錄 行數由數據塊大小以及索引鍵值的長度決定。
對於葉子節點塊來說,其所包含的索引條目與分支節點一樣,都是按照順序排列的(預設是升序排列,也可以在創建索引時指定為降序排列)。每個索引條目(也可以叫做每條記錄)也具有兩個欄位。第一個欄位表示索引的鍵值,對於單列索引來說是一個值;而對於多列索引來說則是多個值組合在一起的。第二個欄位表示鍵值所對應的記錄行的ROWID,該ROWID是記錄行在表裡的物理地址。
當用戶創建索引時,Oracle 取得所有被索引列的數據並進行排序,之後將排序後索引值和與此值相對應的 rowid 按照從下到上的順序載入到索引中。例如,以下語句:
[html] view plain print?在CODE上查看代碼片派生到我的代碼片
CREATE INDEX employees_last_name ON employees(last_name);
Oracle 先將 employees 表按 last_name 列排序,再將排序後的 列及相應的 rowid 按從下到上的順序載入到索引中。使用此索引時,Oracle 可以快速地搜索已排序的 last_name 值,並使用相應的 rowid 去定位包含用戶所查找的 last_name 值的數據行。
在一個平衡樹索引中,最底層的索引塊(葉塊)存儲了被索引的數據值,以及對應的
rowid。葉塊之間以雙向鏈表的形式相互連接。位於葉塊之上的分支塊中包含了
指向下層索引塊的指針。
接下來介紹一個索引查詢的流程,從上往下,第一層為根節點,第二層為分支節點,第三層為葉子節點(包含了列值和rowid)。比如我們的條件為where=29,(補充說明如果被索引的列存儲的是字元數據,那麼索引值為這些字元數據在當前資料庫字元集中的二進制值)就從跟節點開始查詢,29在0-500中,指向分支節點最左邊第一個分支節點塊(也就是B1),就B1中去找,發現29在0-200中,指向葉子節點的L1,於是在L1中找到29的值和響應的rowid。如果只查找索引列的值,就不用根據rowid去表中查找了,如果還要查找值29這行的其他列的值就得根據rowid去表裡查查詢(這個過程叫做回表查詢)。葉子節點還有個雙向鏈表(如圖)。在通過索引進行范圍掃描時會起作用,比如要查找值29-700,如果當查找到值29的時候,不就會再從跟節點開始查找其他的值,而是根據本葉子節點鏈表的指向去查找其他的值。
Ⅶ 如何解決SQL查詢速度太慢
1. 執行計劃中明明有使用到索引,為什麼執行還是這么慢?
2. 執行計劃中顯示掃描行數為 644,為什麼 slow log 中顯示 100 多萬行?
a. 我們先看執行計劃,選擇的索引 「INDX_BIOM_ELOCK_TASK3(TASK_ID)」。結合 sql 來看,因為有 "ORDER BY TASK_ID DESC" 子句,排序通常很慢,如果使用了文件排序性能會更差,優化器選擇這個索引避免了排序。
那為什麼不選 possible_keys:INDX_BIOM_ELOCK_TASK 呢?原因也很簡單,TASK_DATE 欄位區分度太低了,走這個索引需要掃描的行數很大,而且還要進行額外的排序,優化器綜合判斷代價更大,所以就不選這個索引了。不過如果我們強制選擇這個索引(用 force index 語法),會看到 SQL 執行速度更快少於 10s,那是因為優化器基於代價的原則並不等價於執行速度的快慢;
b. 再看執行計劃中的 type:index,"index" 代表 「全索引掃描」,其實和全表掃描差不多,只是掃描的時候是按照索引次序進行而不是行,主要優點就是避免了排序,但是開銷仍然非常大。
Extra:Using where 也意味著掃描完索引後還需要回表進行篩選。一般來說,得保證 type 至少達到 range 級別,最好能達到 ref。
在第 2 點中提到的「慢日誌記錄Rows_examined: 1161559,看起來是全表掃描」,這里更正為「全索引掃描」,掃描行數確實等於表的行數;
c. 關於執行計劃中:「rows:644」,其實這個只是估算值,並不準確,我們分析慢 SQL 時判斷准確的掃描行數應該以 slow log 中的 Rows_examined 為准。
4. 優化建議:添加組合索引 IDX_REL_DEVID_TASK_ID(REL_DEVID,TASK_ID)
優化過程:
TASK_DATE 欄位存在索引,但是選擇度很低,優化器不會走這個索引,建議後續可以刪除這個索引:
select count(*),count(distinct TASK_DATE) from T_BIOMA_ELOCK_TASK;+------------+---------------------------+| count(*) | count(distinct TASK_DATE) |+------------+---------------------------+| 1161559 | 223 |+------------+---------------------------+
在這個 sql 中 REL_DEVID 欄位從命名上看選擇度較高,通過下面 sql 來檢驗確實如此:
select count(*),count(distinct REL_DEVID) from T_BIOMA_ELOCK_TASK;+----------+---------------------------+| count(*) | count(distinct REL_DEVID) |+----------+---------------------------+| 1161559 | 62235 |+----------+---------------------------+
由於有排序,所以得把 task_id 也加入到新建的索引中,REL_DEVID,task_id 組合選擇度 100%:
select count(*),count(distinct REL_DEVID,task_id) from T_BIOMA_ELOCK_TASK;+----------+-----------------------------------+| count(*) | count(distinct REL_DEVID,task_id) |+----------+-----------------------------------+| 1161559 | 1161559 |+----------+-----------------------------------+
在測試環境添加 REL_DEVID,TASK_ID 組合索引,測試 sql 性能:alter table T_BIOMA_ELOCK_TASK add index idx_REL_DEVID_TASK_ID(REL_DEVID,TASK_ID);
添加索引後執行計劃:
這里還要注意一點「隱式轉換」:REL_DEVID 欄位數據類型為 varchar,需要在 sql 中加引號:AND T.REL_DEVID = 000000025xxx >> AND T.REL_DEVID = '000000025xxx'
執行時間從 10s+ 降到 毫秒級別:
1 row in set (0.00 sec)
結論
一個典型的 order by 查詢的優化,添加更合適的索引可以避免性能問題:執行計劃使用索引並不意味著就能執行快。
Ⅷ sql調優的幾種方式
你好,
SQL優化的一些方法
1.對查詢進行優化,應盡量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。
2.應盡量避免在 where 子句中對欄位進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描。
3.應盡量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。
4.應盡量避免在 where 子句中使用 or 來連接條件,否則將導致引擎放棄使用索引而進行全表掃描。
5.in 和 not in 也要慎用,否則會導致全表掃描,
6.下面的查詢也將導致全表掃描:
select id from t where name like '%abc%'
7.應盡量避免在 where 子句中對欄位進行表達式操作,這將導致引擎放棄使用索引而進行全表掃描。
8.應盡量避免在where子句中對欄位進行函數操作,這將導致引擎放棄使用索引而進行全表掃描。
9.不要在 where 子句中的「=」左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引。
10.在使用索引欄位作為條件時,如果該索引是復合索引,那麼必須使用到該索引中的第一個欄位作為條件時才能保證系統使用該索引,否則該索引將不會被使用,並且應盡可能的讓欄位順序與索引順序相一致。
Ⅸ MSSQL資料庫如何優化
1. 保證在實現功能的基礎上,盡量減少對資料庫的訪問次數;通過搜索參數,盡量減少對表的訪問行數,最小化結果集,從而減輕網路負擔;能夠分開的操作盡量分開處理,提高每次的響應速度;、使用SQL時,盡量把使用的索引放在選擇的首列;演算法的結構盡量簡單;在查詢時,不要過多地使用通配符,而且要用到幾列就選擇幾列,如:
SELECT C1,C2 FROM T1;
在可能的情況下盡量限制盡量結果集行數,如:
SELECT TOP 300 C1,C2FROM T1,因為某些情況下用戶是不需要那麼多的數據的, 避免用!=或<> ISNULL或IS NOT NULL、IN ,NOT IN等這樣的操作符,因為這會使系統無法使用索引,而只能直接搜索表中的數據。例如:
SELECT C1 FROM T1 WHERE C1 != 'B%'
2. 合理使用EXISTS,NOT EXISTS子句。如下所示:
1)SELECT SUM(T1.C1)FROM T1 WHERE((SELECTCOUNT(1)FROM T2 WHERE T2.C2=T1.C2)>0)
2)SELECT SUM(T1.C1) FROM T1WHERE EXISTS( SELECT 1 FROM T2 WHERET2.C2=T1.C2)兩者產生相同的結果,但是後者的效率顯然要高於前者。因為後者不會產生大量鎖定的表掃描或是索引掃描。如果你想校驗表裡是否存在某條紀錄,不要用count(*)那樣效率很低,而且浪費伺服器資源。可以用EXISTS代替。如:
IF (SELECT COUNT(1) FROM table_name WHEREcolumn_name = 'xxx')>0
可以寫成:
IF EXISTS (SELECT 1 FROM table_name WHEREcolumn_name = 'xxx')
3. 經常需要寫一個T_SQL語句比較一個父結果集和子結果集,從而找到是否存在在父結果集中有而在子結果集中沒有的記錄,如:
1) SELECTa.C1 FROM T1 a
WHERE NOT EXISTS (SELECT 1 FROM T2 b WHERE a.C1= b.C1)
2) SELECT a.C1 FROM T1 a
LEFT JOIN T2 b ON a.C1 = b.C1 WHERE b.C1IS NULL
3) SELECT a.C1 FROM T1 a
WHERE a.C1 NOT IN (SELECT C1 FROM T2)
三種寫法都可以得到同樣正確的結果,但是效率依次降低。
4. 能夠用BETWEEN的就不要用IN
SELECT * FROM T1 WHERE ID IN (10,11,12,13,14)
改成:
SELECT* FROM T1 WHERE ID BETWEEN 10 AND 14
因為IN會使系統無法使用索引,而只能直接搜索表中的數據。
Ⅹ mysql有幾種索引類型使用索引時都有那些地方要注意sql優化原則是什麼
mysql的索引類型及使用索引時的注意事項有:
一、普通索引。這是最基本的索引,它沒有任何限制。它有以下幾種創建方式:
1、創建索引
代碼如下:
CREATE INDEX indexName ON mytable(username(length));
如果是CHAR,VARCHAR類型,length可以小於欄位實際長度;如果是BLOB和TEXT類型,必須指定 length,下同。
2、修改表結構
代碼如下:
ALTER mytable ADD INDEX [indexName] ON (username(length)) -- 創建表的時候直接指定
CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, INDEX [indexName] (username(length)) );
-- 刪除索引的語法:
DROP INDEX [indexName] ON mytable;
二、唯一索引。它與前面的普通索引類似,不同的就是:索引列的值必須唯一,但允許有空值。如果是組合索引,則列值的組合必須唯一。它有以下幾種創建方式:
代碼如下:
CREATE UNIQUE INDEX indexName ON mytable(username(length))
-- 修改表結構
ALTER mytable ADD UNIQUE [indexName] ON (username(length))
-- 創建表的時候直接指定
CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, UNIQUE [indexName] (username(length)) );
三、主鍵索引。它是一種特殊的唯一索引,不允許有空值。一般是在建表的時候同時創建主鍵索引:
代碼如下:
CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, PRIMARY KEY(ID) );
當然也可以用 ALTER 命令。記住:一個表只能有一個主鍵。
四、組合索引。為了形象地對比單列索引和組合索引,為表添加多個欄位:
代碼如下:
CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, city VARCHAR(50) NOT NULL, age INT NOT NULL );
為了進一步榨取MySQL的效率,就要考慮建立組合索引。就是將 name, city, age建到一個索引里:
代碼如下:
ALTER TABLE mytable ADD INDEX name_city_age (name(10),city,age);[code]
建表時,usernname長度為 16,這里用 10。這是因為一般情況下名字的長度不會超過10,這樣會加速索引查詢速度,還會減少索引文件的大小,提高INSERT的更新速度。
如果分別在 usernname,city,age上建立單列索引,讓該表有3個單列索引,查詢時和上述的組合索引效率也會大不一樣,遠遠低於我們的組合索引。雖然此時有了三個索引,但MySQL只能用到其中的那個它認為似乎是最有效率的單列索引。
建立這樣的組合索引,其實是相當於分別建立了下面三組組合索引:usernname,city,age usernname,city usernname 為什麼沒有 city,age這樣的組合索引呢?這是因為MySQL組合索引「最左前綴」的結果。簡單的理解就是只從最左面的開始組合。並不是只要包含這三列的查詢都會用到該組合索引,下面的幾個SQL就會用到這個組合索引:
[code]
SELECT * FROM mytable WHREE username="admin" AND city="鄭州" SELECT * FROM mytable WHREE username="admin"