當前位置:首頁 » 編程語言 » 為什麼在sql語句中應減少
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

為什麼在sql語句中應減少

發布時間: 2022-06-30 05:15:16

1. 誰能告訴我怎樣優化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數據類型, 你可以索引幾乎所有的列。通常, 在大型表中使用索引特別有效. 當然,你也會發現, 在掃描小表時,使用索引同樣能提高效率。雖然使用索引能得到查詢效率的提高,但是我們也必須注意到它的代價。索引需要空間來存儲,也需要定期維護, 每當有記錄在表中增減或索引列被修改時, 索引本身也會被修改。這意味著每條記錄的INSERT, DELETE , UPDATE將為此多付出4, 5次的磁碟I/O 。因為索引需要額外的存儲空間和處理,那些不必要的索引反而會使查詢反應時間變慢。定期的重構索引是有必要的:ALTER INDEX <INDEXNAME> REBUILD <TABLESPACENAME>
(18)用EXISTS替換DISTINCT:當提交一個包含一對多表信息(比如部門表和雇員表)的查詢時,避免在SELECT子句中使用DISTINCT。一般可以考慮用EXIST替換, EXISTS 使查詢更為迅速,因為RDBMS核心模塊將在子查詢的條件一旦滿足後,立刻返回結果。例子:(低效):
SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D , EMP E
WHERE D.DEPT_NO = E.DEPT_NO
(高效):
SELECT DEPT_NO,DEPT_NAME FROM DEPT D WHERE EXISTS ( SELECT 『X'
FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO);
(19)SQL語句用大寫的;因為Oracle總是先解析SQL語句,把小寫的字母轉換成大寫的再執行。(20)在Java代碼中盡量少用連接符「+」連接字元串。(21)避免在索引列上使用NOT通常,我們要避免在索引列上使用NOT, NOT會產生在和在索引列上使用函數相同的影響。當Oracle「遇到」NOT,他就會停止使用索引轉而執行全表掃描。(22)避免在索引列上使用計算。WHERE子句中,如果索引列是函數的一部分。優化器將不使用索引而使用全表掃描。舉例:低效:
SELECT … FROM DEPT WHERE SAL * 12 > 25000;
高效:
SELECT … FROM DEPT WHERE SAL > 25000/12;
(23)用>=替代>:高效:
SELECT * FROM EMP WHERE DEPTNO >=4
低效:
SELECT * FROM EMP WHERE DEPTNO >3
兩者的區別在於, 前者DBMS將直接跳到第一個DEPT等於4的記錄而後者將首先定位到DEPTNO=3的記錄並且向前掃描到第一個DEPT大於3的記錄。(24)用UNION替換OR (適用於索引列):通常情況下, 用UNION替換WHERE子句中的OR將會起到較好的效果。對索引列使用OR將造成全表掃描。注意, 以上規則只針對多個索引列有效. 如果有column沒有被索引, 查詢效率可能會因為你沒有選擇OR而降低。在下面的例子中, LOC_ID 和REGION上都建有索引。高效:
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE LOC_ID = 10
UNION
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE REGION = 「MELBOURNE」
低效:
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE LOC_ID = 10 OR REGION = 「MELBOURNE」
(25)用IN來替換OR:這是一條簡單易記的規則,但是實際的執行效果還須檢驗,在Oracle8i下,兩者的執行路徑似乎是相同的:低效:SELECT…. FROM LOCATION WHERE LOC_ID = 10 OR LOC_ID = 20 OR LOC_ID = 30高效:SELECT… FROM LOCATION WHERE LOC_IN IN (10,20,30);(26)避免在索引列上使用IS NULL和IS NOT NULL:避免在索引中使用任何可以為空的列,Oracle將無法使用該索引。對於單列索引,如果列包含空值,索引中將不存在此記錄。對於復合索引,如果每個列都為空,索引中同樣不存在此記錄.如果至少有一個列不為空,則記錄存在於索引中。舉例: 如果唯一性索引建立在表的A列和B列上, 並且表中存在一條記錄的A,B值為(123,null) , Oracle將不接受下一條具有相同A,B值(123,null)的記錄(插入)。 然而如果所有的索引列都為空,Oracle將認為整個鍵值為空而空不等於空。因此你可以插入1000 條具有相同鍵值的記錄,當然它們都是空! 因為空值不存在於索引列中,所以WHERE子句中對索引列進行空值比較將使ORACLE停用該索引。低效: (索引失效)SELECT … FROM DEPARTMENT WHERE DEPT_CODE IS NOT NULL;高效: (索引有效)SELECT … FROM DEPARTMENT WHERE DEPT_CODE >=0;(27)總是使用索引的第一個列:如果索引是建立在多個列上, 只有在它的第一個列(leading column)被where子句引用時,優化器才會選擇使用該索引。這也是一條簡單而重要的規則,當僅引用索引的第二個列時,優化器使用了全表掃描而忽略了索引。(28)用UNION-ALL 替換UNION ( 如果有可能的話):當SQL語句需要UNION兩個查詢結果集合時,這兩個結果集合會以UNION-ALL的方式被合並, 然後在輸出最終結果前進行排序。如果用UNION ALL替代UNION, 這樣排序就不是必要了。效率就會因此得到提高。需要注意的是,UNION ALL 將重復輸出兩個結果集合中相同記錄。因此各位還是要從業務需求分析使用UNION ALL的可行性. UNION 將對結果集合排序,這個操作會使用到SORT_AREA_SIZE這塊內存。對於這塊內存的優化也是相當重要的。下面的SQL可以用來查詢排序的消耗量:
低效:
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
UNION
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
高效:
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
UNION ALL
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
(29)用WHERE替代ORDER BY:ORDER BY 子句只在兩種嚴格的條件下使用索引。ORDER BY中所有的列必須包含在相同的索引中並保持在索引中的排列順序。ORDER BY中所有的列必須定義為非空。WHERE子句使用的索引和ORDER BY子句中所使用的索引不能並列。例如: 表DEPT包含以下列:DEPT_CODE PK NOT NULLDEPT_DESC NOT NULLDEPT_TYPE NULL低效: (索引不被使用)SELECT DEPT_CODE FROM DEPT ORDER BY DEPT_TYPE高效: (使用索引)SELECT DEPT_CODE FROM DEPT WHERE DEPT_TYPE > 0(30)避免改變索引列的類型:當比較不同數據類型的數據時, ORACLE自動對列進行簡單的類型轉換。 假設 EMPNO是一個數值類型的索引列:SELECT … FROM EMP WHERE EMPNO = 『123'。 實際上,經過Oracle類型轉換, 語句轉化為: SELECT … FROM EMP WHERE EMPNO = TO_NUMBER(『123') 。幸運的是,類型轉換沒有發生在索引列上,索引的用途沒有被改變。現在,假設EMP_TYPE是一個字元類型的索引列:SELECT … FROM EMP WHERE EMP_TYPE = 123 。這個語句被Oracle轉換為: SELECT … FROM EMP WHERETO_NUMBER(EMP_TYPE)=123。因為內部發生的類型轉換, 這個索引將不會被用到! 為了避免Oracle對你的SQL進行隱式的類型轉換, 最好把類型轉換用顯式表現出來。注意當字元和數值比較時, Oracle會優先轉換數值類型到字元類型。(31)需要當心的WHERE子句:某些SELECT 語句中的WHERE子句不使用索引。這里有一些例子:(1)『!=' 將不使用索引。記住, 索引只能告訴你什麼存在於表中, 而不能告訴你什麼不存在於表中。(2)『||'是字元連接函數。就象其他函數那樣, 停用了索引。(3)『+'是數學函數。就象其他數學函數那樣, 停用了索引。(4)相同的索引列不能互相比較,這將會啟用全表掃描。(32)a. 如果檢索數據量超過30%的表中記錄數.使用索引將沒有顯著的效率提高。b. 在特定情況下, 使用索引也許會比全表掃描慢, 但這是同一個數量級上的區別。而通常情況下,使用索引比全表掃描要塊幾倍乃至幾千倍!(33)避免使用耗費資源的操作:帶有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL語句會啟動SQL引擎執行耗費資源的排序(SORT)功能。DISTINCT需要一次排序操作, 而其他的至少需要執行兩次排序. 通常, 帶有UNION, MINUS , INTERSECT的SQL語句都可以用其他方式重寫. 如果你的資料庫的SORT_AREA_SIZE調配得好, 使用UNION , MINUS, INTERSECT也是可以考慮的, 畢竟它們的可讀性很強。(34)優化GROUP BY:提高GROUP BY 語句的效率, 可以通過將不需要的記錄在GROUP BY 之前過濾掉。下面兩個查詢返回相同結果但第二個明顯就快了許多。
低效:
SELECT JOB, AVG(SAL)
FROM EMP
GROUP JOB
HAVING JOB = 'PRESIDENT'
OR JOB = 'MANAGER'高效:
SELECT JOB, AVG(SAL)
FROM EMP
WHERE JOB = 'PRESIDENT'
OR JOB = 'MANAGER'
GROUP JOB

2. sql 請闡述為什麼應該盡量減少「SELECT *」這類語句的使用

SELECT--SQL語法
從一個或多個表中檢索數據。SELECT SQL 命令是與其它 Vfp一樣的內置的 Vfp命令。當你使用 SELECT 來生成查詢時, Vfp翻譯查詢並從表中獲取指定數據。你可以從以下地方創建 SELECT 查詢:

「命令」窗口中
帶有其它任何 Vfp命令的 Vfp程序中
查詢設計器中
SELECT [ALL | DISTINCT] [TOP nExpr [PERCENT]] [Alias.] Select_Item
[[AS] Column_Name] [, [Alias.] Select_Item [[AS] Column_Name] ...]
FROM [FORCE] [DatabaseName!] Table [[AS] Local_Alias]
[ [INNER | LEFT [OUTER] | RIGHT [OUTER] | FULL [OUTER] JOIN DatabaseName!]
Table [[AS] Local_Alias] [ON JoinCondition ...]
[[INTO Destination] | [TO FILE FileName [ADDITIVE] | TO PRINTER [PROMPT] | TO SCREEN]]
[PREFERENCE PreferenceName] [NOCONSOLE] [PLAIN] [NOWAIT]
[WHERE JoinCondition [AND JoinCondition ...] [AND | OR FilterCondition [AND | OR FilterCondition ...]]]
[Group By GroupColumn [, GroupColumn ...]] [HAVING FilterCondition] [UNION [ALL] SELECTCommand]
[Order By Order_Item [ASC | DESC] [, Order_Item [ASC | DESC] ...]]
參數
SELECT
在 SELECT 子句中指定在查詢結果中包含的欄位、常量和表達式。
ALL
查詢結果中包含所有行 ( 包括重復值 )。ALL 是默認設置。
DISTINCT
在查詢結果中剔除重復的行。每一個 SELECT 子句只能使用一次 DISTINCT。
TOP nExpr [PERCENT]
在符合查詢條件的所有記錄中,選取指定數量或百分比的記錄。TOP 子句必須與 ORDER BY 子句同時使用。ORDER BY 子句指定查詢結果中包含的列上由Top字句決定的行數, TOP 子句根據此排序選定最開始的 nExpr個或 nExpr% 的記錄。

您可以指定選取 1 到 32767 個記錄。使用 ORDER BY 子句指定的欄位進行排序,會產生並列的情況,比如,可能有多個記錄,它們在選定的欄位上相同;所以,如果您指定 nExpr 為 10,在查詢結果中可能多於 10 個記錄,因為可能有幾個記錄位置並列。

如果包含 PERCENT 關鍵字指定查詢結果中的記錄數,得到記錄數的可能是小數,這時進行取整。包含 PERCENT 關鍵字時,nExpr 的范圍是 0.01 到 99.99。

[Alias.] Select_Item
限定匹配項的名稱。Select_Item 指定的每一項在查詢結果中都生成一列。一個項可以是以下一個
FROM 子句所包含的表中的欄位名稱。
一個常量,查詢結果中每一行都出現這個常量值。
一個表達式,可以是用戶自定義函數名。
關於使用用戶定義函數的詳細信息, 參見注釋節中的帶用戶定義函數的 SELECT。

你用 Select_Item 指定的各項生成一個查詢結果列。

如果兩個或更多的項具有相同的名稱, 在項名前包含表別名和一個句點來避免列重復。

[AS] Column_Name
為查詢輸出中的列指定顯示名。Column_Name 可以是表達式但不能包含不允許的字元, 如, 欄位名中的空格。
當 Select_Item 是一個表達式或包含一個欄位函數而且你想給該列一個有意義的名字時該選項是有用的。

FROM [FORCE] DatabaseName!
列出所有從中檢索數據的表。
FORCE 指定連接表時按它們出現在 FROM 子句中的順序。如果省略 FORCE, Vfp會試圖對查詢進行優化。但是, 使用 FORCE 子句,避免了優化過程,可能加快查詢執行的速度。

當包含表的資料庫不是當前資料庫時,DatabaseName! 指定這個資料庫的名稱。如果資料庫不是當前資料庫,就必須指定包含表的資料庫名稱。應在資料庫名稱之後表名之前加上感嘆號(!)分隔符。

[[AS] Local_Alias]
為 Table 中的表指定一個臨時名稱。如果指定了本地別名,那麼在整個SELECT 語句中必須都用這個別名代替表名。本地別名不影響 Visual FoxPro環境。INNER JOIN 只有在其他表中包含對應記錄(一個或多個)的記錄才出現在查詢結果中。
INNER JOIN 只有在其他表中包含對應記錄(一個或多個)的記錄才出現在查詢結果中。

LEFT [OUTER] JOIN 在查詢結果中包含:JOIN 左側表中的所有記錄,以及JOIN 右側表中匹配的記錄。OUTER 關鍵字可被省略;包含 OUTER 強調這是一個外連接 (outer join)。

RIGHT [OUTER] JOIN 在查詢結果中包含:JOIN 右側表中的所有記錄,以及 JOIN 左側表中匹配的記錄。OUTER 關鍵字可被省略;包含 OUTER 強調這是一個外連接接 (outer join)。

FULL [OUTER] JOIN 在查詢結果中包含:JOIN 兩側所有的匹配記錄,和不匹配的記錄;包含 OUTER 強調這是一個外連接 (outer join)。

關於連接的詳細信息, 參見備注段中的 Joins。

ON JoinCondition 指定連接條件。

INTO Destination
指定在何處保存查詢結果。Destination 可以是下列子句之一:
ARRAY ArrayName ,將查詢結果保存到變數數組中。
如果查詢結果中不包含任何記錄,則不創建這個數組。

CURSOR CursorName [NOFILTER | READWRITE] 將查詢結果保存到臨時表中。
要創建一個查用於子查詢中的游標, 用 NOFILTER。關於 NOFILTER 的詳細信息, 參見備注節。

要指定游標是臨時的和可修改的, 使用 READWRITE。如果源表或表使用 autoincrementing, 該設置不會被 READWRITE 游標繼承。

DBF | TABLE TableName [DATABASE DatabaseName [NAME LongTableName]] 保存查詢結果到一個表中。
包含 DATABASE DatabaseName 以指定添加了表的資料庫。

包含 NAME LongTableName 可以為該表命一個最多可包括 128 個字元的並且可以在資料庫中代替短名字的長名。

如果沒有包括 INTO 子句, 查詢結果顯示在一個「瀏覽」窗口中。也可以用 TO FILE 子句來定向查詢結果到列印機或一個文件。

TO FILE FileName [ADDITIVE] | TO PRINTER [PROMPT] | TO SCREEN
定向查詢結果到列印機或一個文件。
ADDITIVE 添加查詢輸出到 TO FILE FileName 中指定的已存在的文本文件內容中。

TO PRINTER 定向查詢輸出到一個列印機。在列印開始之前,使用可選的 PROMPT 子句顯示一個對話框。您可以根據當前安裝的列印機驅動程序調整列印機的設置。將 PROMPT 子句放置在緊跟 TO PRINTER 之後。

TO SCREEN 使查詢結果定向輸出到 Vfp主窗口或活動的用戶自定義窗口中。

PREFERENCE PreferenceName
如果查詢結果送往瀏覽窗口,就可以使用 PREFERENCE 保存瀏覽窗口的屬性和選項以備後用。關於 PREFERENCE 功能的詳細信息, 參見備注節。
NOCONSOLE
不顯示送到文件、列印機或 Vfp主窗口的查詢結果。
PLAIN
防止列標題出現在顯示的查詢結果中。不管有無 TO 子句都可使用 PLAIN子句。如果 SELECT 語句中包括 INTO 子句,則忽略 PLAIN 子句。
NOWAIT
打開瀏覽窗口並將查詢結果輸出到這個窗口後繼續程序的執行。程序並不等待關閉瀏覽窗口,而是立即執行緊接在 SELECT 語句後面的程序行。關於如何使用 NOWAIT 的說明, 參見備注節。
WHERE JoinCondition
指定 Vfp的查詢結果中只包括符合指定條件的記錄。JoinCondition 指定位於 FROM 子句中的欄位連接表。關於指定連接條件的詳細信息, 參見備注節。
WHERE 支持 JoinCondition 的 ESCAPE 操作符, 讓你可以執行包含有百分號 (%) 和下劃線 (_) 通配符的 SELECT SQL 命令查詢。ESCAPE 允許你指定一個按原字樣處理的 SELECT SQL 命令通配符。在 ESCAPE 子句中, 一旦一個字元被放到通配符字元之前,就表示這個通配符被看作一個文字字元。

FilterCondition
指定將包含在查詢結果中記錄必須符合的條件。使用 AND 或 OR 操作符,您可以包含隨意數目的過濾條件。您還可以使用 NOT 操作符將邏輯表達式的值取反,或使用 EMPTY() 函數以檢查空欄位。
SELECT SQL 命令在篩選條件中支持 "<field> IS / IS NOT NULL"。要學習如何使用 FilterCondition。

Group By GroupColumn [, GroupColumn ...]
按列的值對查詢結果的行進行分組。GroupColumn 可以是常規的表欄位名,也可以是一個包含 SQL 欄位函數的欄位名,還可以是一個數值表達式,指定查詢結果表中的列位置(最左邊的列編號為 1 )。
HAVING FilterCondition
指定包括在查詢結果中的組必須滿足的篩選條件。HAVING 應該同 GROUP BY一起使用。它能包含數量不限的篩選條件,篩選條件用 AND 或 OR 連接,還可以使用 NOT 來對邏輯表達式求反。可以在 HAVING 子句中使用本地別名和欄位函數。 關於你可以使用的欄位函數的詳細信息, 參見備注節。FilterCondition 不能包含子查詢。
可以使用帶 HAVING 子句的 Group By。使用 HAVING 子句的命令如果沒有使用 GROUP BY 子句,則它的作用與WHERE 子句相同。
如果 HAVING 子句不包含欄位函數的話,使用 WHERE 子句可以獲得較快的速度。

HAVING 子句應該出現在 INTO 子句前否則產生錯誤。

[UNION [ALL] SELECTCommand]
把一個 SELECT 語句的最後查詢結果同另一個 SELECT 語句最後查詢結果組合起來。默認情況下,UNION 檢查組合的結果並排除重復的行。
要組合多個UNION 子句,可使用括弧。可以用 UNION 子句模擬一個外部聯接。
ALL 防止 UNION 刪除組合結果中重復的行。

當一個列是備注或通用型時, 不允許連接不同類型的列。

在 Vfp8.0 以前的版本中, 當在兩個不同類型的欄位上執行 UNION 操作時你需要執行明確的轉換。
Vfp現在對支持它的數據類型支持隱含數據類型轉換。關於隱含數據類型轉換和數據類型優先, UNION 子句允許的規則, 以及其它信息的詳細內容, 參見備注節中的數據類型轉換和優先。

Order By Order_Item [ASC | DESC]
根據列的數據對查詢結果進行排序。每個 Order_Item 都必須對應查詢結果中的一列。它可以是下列之一:
FROM 子句中表的欄位,同時也是 SELECT 主句(不在子查詢中)的一個選擇項。
一個數值表達式,表示查詢結果中列的位置(最左邊列編號為 1 )。
ASC 指定查詢結果根據排序項以升序排列。它是 ORDER BY 的默認選項。

DESC 指定查詢結果以降序排列。

備注
在使用 FROM 子句時如果沒有打開表, Vfp顯示「打開」對話框讓你指定文件位置。一但打開後, 表在查詢完成後仍然保持打開。

當在 Destination 參數中使用 CURSOR 子句時, 如果你指定了一個打開的表的名字, Vfp產生一條錯誤信息。在 SELECT 執行後, 臨時游標保持打開並是活動的和只讀的除非你指定了 READWRITE 選項。當你關閉該臨時游標時, 它被刪除。游標可以指定 SORTWORK 而成為存在於驅動器或卷上的臨時文件。

當在 Destination 參數中使用 CURSOR 子句時, 你現在可以使用 NOFILTER 來創建一個可用於後來的查詢的游標。在早期版本的 Vfp中, 你需要包括一個額外的常數或表達式作為篩選。例如, 添加一個邏輯 true 作為篩選表達式來創建一個可用於後來的查詢的查詢:

SELECT *, .T. FROM customers INTO CURSOR myquery
但是, 包括 NOFILTER 會降低查詢性能因為要在磁碟上創建一個臨時表。臨時表在游標關閉時從磁碟上刪除。

當在 Destination 參數中使用 DBF | TABLE 子句時, 如果你指定了一個已經打開的表, 而且 SET SAFETY 是設置為 OFF, Vfp不警告地復寫該表。如果你沒有指定一個擴展名, Vfp給表一個 .dbf 擴展名。在 SELECT 執行後表保持打開並且是活動的。

如果你在相同查詢中包括 INTO 和 TO 子句, Vfp忽略 TO 子句。如果你包括 TO 子句但沒有包括 INTO 子句, 你可以定向查詢結果到一個名為 FileName 的 ASCII 文本文件, 到列印機, 或到 Vfp主窗口。

PREFERENCE 把特徵, 屬性或參數選項長期保存在 FoxUser.dbf 資源文件中。Preferences 可以在任何時候獲取。第一次執行有 PREFERENCE Preference Name 的 SELECT 命令時創建參數選項。以後執行有相同參數選項名的 SELECT 命令時便將瀏覽窗口恢復到原來的參數選項狀態。當瀏覽窗口關閉時,更新參數選項。如果您按下 CTRL+Q+W 鍵退出「瀏覽」窗口,您對「瀏覽」窗口所做的更改不會保存到資源文件中。

SELECT 命令中包括 TO SCREEN 可以把查詢結果定向輸出到 Vfp主窗口或用戶自定義窗口。如果顯示時 Vfp主窗口或用戶自定義窗口中寫滿了一屏,就暫停輸出。按任意鍵可以查看查詢結果後面的內容。但是,如果命令中包括了 NOWAIT 子句,顯示查詢結果時就不會暫停,等待按鍵,而是在 Vfp主窗口或用戶自定義窗口中連續滾過所有內容。如果命令中包含有 INTO 子句,忽略 NOWAIT 子句。

在一個 SQL 查詢的 WHERE 子句中包括 EVALUATE() 函數會返回不正確的數據。

如果包括一個以上的表在查詢中, 你應該在第一個以後為每一個表指定一個連接條件。連接條件可以包含篩選條件。

注意 每一個 SELECT 語句的最大連接數是 9.
必須用 AND 操作符來連接多個連接條件。各連接條件具有以下格式:

當你在串中使用 = 操作符時, 它的動作根據 SET ANSI 的設置會不同。當 SET ANSI 設置為 OFF 時, Vfp只比較串到較短串結束。當 SET ANSI 設置為 ON 時, Vfp遵循 ANSI 標準的字元串比較。關於 Vfp如果執行字元串比較的額外信息, 參見 SET ANSI 和 SET EXACT。

下列欄位函數可以與選定項一起使用,選定項可以是一個欄位或包含欄位的表達式:

AVG(Select_Item), 計算列中數值的平均值。
COUNT(Select_Item), 計算列中選定項的數目。計算查詢輸出的行數。COUNT(*) 計算查詢輸出中的行數。
MIN(Select_Item), 確定列中 Select_Item 的最小值。
MAX(Select_Item), 確定列中 Select_Item 的最大值。
SUM(Select_Item), 計算列中數值的和。
欄位函數不能嵌套使用。

UNION 子句遵守下列規則:

不能使用 UNION 來組合子查詢。
兩個 SELECT 命令的查詢結果中的列數必須相同。
兩個 SELECT 查詢結果中的對應列必須有相同的數據類型和寬度。
只有最後的 SELECT 中可以包含 ORDER BY 子句,而且必須按編號指出所輸出的列。如果包含了一個 ORDER BY 子句,它將影響整個結果。
當你用 UNION 連接查詢中的兩個表時, 僅匹配連接欄位值的記錄會出現在查詢結果中。如果在父表中的記錄在子表中沒有相應的記錄, 父表中的記錄不會出現在查詢結果中。一個外部聯接允許你包括父表中的所有記錄到輸出結果中, 連同子表中的匹配記錄一起。要在 Vfp中創建一個外部聯接, 你需要要使用一個嵌套的 SELECT 命令
注意 確信在每一個分號前包括一個空格。否則, Vfp產生一個錯誤。
上例中, 在 UNION 子句前的部分的命令從兩個表中選擇具有匹配值的記錄。不包括沒有相關的發票的客戶公司。命令中 UNION 子句後的部分選擇客戶表中的在訂單表中無匹配記錄的記錄。

關於第二部分的命令, 注意以下幾點:

包括在園括弧中的 SELECT 語句首先處理。該語句的結果是選擇訂單表中的所有客戶編號。
WHERE 子句找出 customer 表中的在 orders 表沒有相關記錄的所有客戶編號。由於第一節中的命令提供了所在 orders 表中有客戶編號的公司, Customer 表中的所有公司現在都包含在查詢結果中了。
因為在 UNION 中的表的結構必須相同, 有兩個佔位符在第二個 SELECT 語句中來代表第一個 SELECT 語句中的 orders.order_id 和 orders.emp_id。
注意 佔位符必須與它們所代表的欄位有相同類型。如果欄位是日期型, 佔位符應該是 。如果欄位是一個字元欄位, 佔位符應該是一個空串 ("")。

如果你沒有在 Order By 子句中指定排序, 查詢結果顯示為未排序。

當你發出 SET TALK ON 並執行 SELECT 時, Vfp顯示查詢使用的時間和結果中的記錄數。 _TALLY 包含了在查詢結果中的記錄數。

SET FILTER 設置的篩選條件對 SELECT 命令不起作用。

注意 下面部分提到的子查詢, 是指在 SELECT 命令中包含的 SELECT 命令。子查詢必須包括在園括弧中。在 SELECT 命令的 WHERE 子句中可以包含最多兩個平級的(非嵌套)的子查詢。子查詢中可以有多個連接條件 (join conditions)。
在你創建查詢輸出時, 列的命名遵循如下規則:

如果選擇項是具有唯一名稱的欄位,則用欄位名作為輸出列名。
如果多個選擇項具有相同名稱。例如,如果名為 Customer 的表有一個STREET 欄位,而名為 Employees 的表也有一個 STREET 欄位,則輸出列命名為 Extension_A 和 Extension_B (STREET_A 和 STREET_B)。如果選擇項名稱有 10 字元長,可以將名稱截短後再加下劃線和字母。例如,DEPARTMENT 變為 DEPARTME_A。
如果選擇項是表達式,它的輸出列命名為 EXP_A。其他表達式分別命名為EXP_B、EXP_C,依此類推。
如果選擇項包含諸如 COUNT() 這樣的欄位函數,則輸出列命名為CNT_A。如果另一個選擇項包含 SUM(),它的輸出列命名為 SUM_B。
用戶定義函數和 在 SELECT 子句中使用用戶自定義函數有明顯優點,但使用時應考慮以下限制:

SELECT 子句的運行速度會受用戶自定義函數執行速度的影響。因此,如果使用戶自定義函數的操作量很大,則這些函數的功能最好調用 C 語言或匯編語言編寫的 API 或用戶自定義函數來完成。
在 SELECT 激活的用戶自定義函數中,很難預測 Vfp輸入/輸出(I/O)和表的環境。一般來說,不知道選擇的工作區是哪一個,不知道當前表的名稱,甚至不知道正在處理的欄位名。這些變數的值完全取決於用戶自定義函數在優化過程的什麼地方激活。
在 SELECT 子句調用的用戶自定義函數中修改 VfpI/O 或表的環境是很不安全的。一般來說,這樣做的結果難以預料。
從 SELECT 將值傳遞給用戶自定函數唯一可靠的方法,是激活用戶自定義函數時以參數的形式傳遞。
經過實踐,有可能發現某種被認為是違法的操作在某種 FoxPro 版本中運行正確,但這並不保證它在以後的版本中也能正確運行。
拋開這些限制不說,用戶自定義函數在 SELECT 語句中還是可接受的。但不要忘記使用 SELECT 可能要降低性能。要學習如何在 SELECT 中使用用戶定義函數, 參見示例節。

連接 Vfp支持 ANSI SQL '92 連接 (Join) 語法,通過比較兩個或多個表中的欄位,將它們的記錄連接到一起,生成查詢。例如,內部連接 (inner join) 是將兩個表中連接欄位 (joined field) 值相同的記錄選取到查詢中。Vfp支持嵌套連接(nested joins)

由於 SQL 是派生於數學集合理論, 各表可以代表一個環。指定連接條件的 ON 子句確定交接點, 它代表匹配的行集合。對於一個內部聯接, 交接發生在兩個環的內部或 "inner" 部分。一個外聯接不僅僅包括這些表內部的交叉區域匹配的行, 也包括環的外面的左或右部的交集的行。

3. 為什麼存儲過程執行速度比普通的SQL快而且減少網路流量

存儲過程所以快是因為他是預先編譯的,當然節省了編譯的時間。減少網路流量是指減少與客戶端之間的交互,在伺服器上執行運算,最後只把結果反給客戶端,所以流量少。

比如你查詢個內容,需要先查一個表,根據結果再查另外一個表。不用存儲過程你怎麼做呢?自然是先讀出那個表的內容來,然後在asp/asp.net/php里,用代碼生成一個語句再去查詢,這樣要往復2,3次。而用存儲過程就可以直接在伺服器上運算,只要一次來回就ok了,自然網路流量就減少

因為在存儲過程中的SQL語句是已經經過了語法檢查和編譯的,可以直接執行;而SQL總要先進行語法解析和編譯才能執行。另外對於網路執行的話,執行相同的任務,客戶端調用存儲過程的代碼傳輸量和直接執行SQL語句相比也要更少。

4. 為什麼應該盡量減少「SELECT *」這類語句的使用

因為使用select * 會將所有欄位的值全都取出,會增加數據的冗餘,如果用於網站數據的話,會增加伺服器的負擔。因此盡量明確需要查詢的欄位值。

個人見解。希望有所幫助。

5. 如何優化SQL語句

一、問題的提出
在應用系統開發初期,由於開發資料庫數據比較少,對於查詢SQL語句,復雜視圖的的編寫等體會不出SQL語句各種寫法的性能優劣,但是如果將應用系統提交實際應用後,隨著資料庫中數據的增加,系統的響應速度就成為目前系統需要解決的最主要的問題之一。系統優化中一個很重要的方面就是SQL語句的優化。對於海量數據,劣質SQL語句和優質SQL語句之間的速度差別可以達到上百倍,可見對於一個系統不是簡單地能實現其功能就可,而是要寫出高質量的SQL語句,提高系統的可用性。
在多數情況下,Oracle使用索引來更快地遍歷表,優化器主要根據定義的索引來提高性能。但是,如果在SQL語句的where子句中寫的SQL代碼不合理,就會造成優化器刪去索引而使用全表掃描,一般就這種SQL語句就是所謂的劣質SQL語句。在編寫SQL語句時我們應清楚優化器根據何種原則來刪除索引,這有助於寫出高性能的SQL語句。
二、SQL語句編寫注意問題
下面就某些SQL語句的where子句編寫中需要注意的問題作詳細介紹。在這些where子句中,即使某些列存在索引,但是由於編寫了劣質的SQL,系統在運行該SQL語句時也不能使用該索引,而同樣使用全表掃描,這就造成了響應速度的極大降低。
1.
IS
NULL

IS
NOT
NULL
不能用null作索引,任何包含null值的列都將不會被包含在索引中。即使索引有多列這樣的情況下,只要這些列中有一列含有null,該列就會從索引中排除。也就是說如果某列存在空值,即使對該列建索引也不會提高性能。
任何在where子句中使用is
null或is
not
null的語句優化器是不允許使用索引的。
2.
聯接列
對於有聯接的列,即使最後的聯接值為一個靜態值,優化器是不會使用索引的。我們一起來看一個例子,假定有一個職工表(employee),對於一個職工的姓和名分成兩列存放(FIRST_NAME和LAST_NAME),現在要查詢一個叫比爾.柯林頓(Bill
Cliton)的職工。
下面是一個採用聯接查詢的SQL語句,
select
*
from
employss
where
first_name||''||last_name
='Beill
Cliton';
上面這條語句完全可以查詢出是否有Bill
Cliton這個員工,但是這里需要注意,系統優化器對基於last_name創建的索引沒有使用。
當採用下面這種SQL語句的編寫,Oracle系統就可以採用基於last_name創建的索引。
***
where
first_name
='Beill'
and
last_name
='Cliton';
.
帶通配符(%)的like語句
同樣以上面的例子來看這種情況。目前的需求是這樣的,要求在職工表中查詢名字中包含cliton的人。可以採用如下的查詢SQL語句:
select
*
from
employee
where
last_name
like
'%cliton%';
這里由於通配符(%)在搜尋詞首出現,所以Oracle系統不使用last_name的索引。在很多情況下可能無法避免這種情況,但是一定要心中有底,通配符如此使用會降低查詢速度。然而當通配符出現在字元串其他位置時,優化器就能利用索引。在下面的查詢中索引得到了使用:
select
*
from
employee
where
last_name
like
'c%';
4.
Order
by語句
ORDER
BY語句決定了Oracle如何將返回的查詢結果排序。Order
by語句對要排序的列沒有什麼特別的限制,也可以將函數加入列中(象聯接或者附加等)。任何在Order
by語句的非索引項或者有計算表達式都將降低查詢速度。
仔細檢查order
by語句以找出非索引項或者表達式,它們會降低性能。解決這個問題的辦法就是重寫order
by語句以使用索引,也可以為所使用的列建立另外一個索引,同時應絕對避免在order
by子句中使用表達式。
5.
NOT
我們在查詢時經常在where子句使用一些邏輯表達式,如大於、小於、等於以及不等於等等,也可以使用and(與)、or(或)以及not(非)。NOT可用來對任何邏輯運算符號取反。下面是一個NOT子句的例子:
...
where
not
(status
='VALID')
如果要使用NOT,則應在取反的短語前面加上括弧,並在短語前面加上NOT運算符。NOT運算符包含在另外一個邏輯運算符中,這就是不等於(<>)運算符。換句話說,即使不在查詢where子句中顯式地加入NOT詞,NOT仍在運算符中,見下例:
...
where
status
<>'INVALID';
對這個查詢,可以改寫為不使用NOT:
select
*
from
employee
where
salary<3000
or
salary>3000;
雖然這兩種查詢的結果一樣,但是第二種查詢方案會比第一種查詢方案更快些。第二種查詢允許Oracle對salary列使用索引,而第一種查詢則不能使用索引。
雖然這兩種查詢的結果一樣,但是第二種查詢方案會比第一種查詢方案更快些。第二種查詢允許Oracle對salary列使用索引,而第一種查詢則不能使用索引。

6. 如何能縮短sql語句的執行時間

1. SQL優化的原則是:將一次操作需要讀取的BLOCK數減到最低,即在最短的時間達到最大的數據吞吐量。
調整不良SQL通常可以從以下幾點切入:
? 檢查不良的SQL,考慮其寫法是否還有可優化內容
? 檢查子查詢 考慮SQL子查詢是否可以用簡單連接的方式進行重新書寫
? 檢查優化索引的使用
? 考慮資料庫的優化器

2. 避免出現SELECT * FROM table 語句,要明確查出的欄位。

3. 在一個SQL語句中,如果一個where條件過濾的資料庫記錄越多,定位越准確,則該where條件越應該前移。

4. 查詢時盡可能使用索引覆蓋。即對SELECT的欄位建立復合索引,這樣查詢時只進行索引掃描,不讀取數據塊。

5. 在判斷有無符合條件的記錄時建議不要用SELECT COUNT (*)和select top 1 語句。

6. 使用內層限定原則,在拼寫SQL語句時,將查詢條件分解、分類,並盡量在SQL語句的最里層進行限定,以減少數據的處理量。

7. 應絕對避免在order by子句中使用表達式。

8. 如果需要從關聯表讀數據,關聯的表一般不要超過7個。

9. 小心使用 IN 和 OR,需要注意In集合中的數據量。建議集合中的數據不超過200個。

10. <> 用 < 、 > 代替,>用>=代替,<用<=代替,這樣可以有效的利用索引。

11. 在查詢時盡量減少對多餘數據的讀取包括多餘的列與多餘的行。

12. 對於復合索引要注意,例如在建立復合索引時列的順序是F1,F2,F3,則在where或order by子句中這些欄位出現的順序要與建立索引時的欄位順序一致,且必須包含第一列。只能是F1或F1,F2或F1,F2,F3。否則不會用到該索引。

13. 多表關聯查詢時,寫法必須遵循以下原則,這樣做有利於建立索引,提高查詢效率。格式如下select sum(table1.je) from table1 table1, table2 table2, table3 table3 where (table1的等值條件(=)) and (table1的非等值條件) and (table2與table1的關聯條件) and (table2的等值條件) and (table2的非等值條件) and (table3與table2的關聯條件) and (table3的等值條件) and (table3的非等值條件)。
注:關於多表查詢時from 後面表的出現順序對效率的影響還有待研究。

14. 子查詢問題。對於能用連接方式或者視圖方式實現的功能,不要用子查詢。例如:select name from customer where customer_id in ( select customer_id from order where money>1000)。應該用如下語句代替:select name from customer inner join order on customer.customer_id=order.customer_id where order.money>100。

15. 在WHERE 子句中,避免對列的四則運算,特別是where 條件的左邊,嚴禁使用運算與函數對列進行處理。比如有些地方 substring 可以用like代替。

16. 如果在語句中有not in(in)操作,應考慮用not exists(exists)來重寫,最好的辦法是使用外連接實現。

17. 對一個業務過程的處理,應該使事物的開始與結束之間的時間間隔越短越好,原則上做到資料庫的讀操作在前面完成,資料庫寫操作在後面完成,避免交叉。

18. 請小心不要對過多的列使用列函數和order by,group by等,謹慎使用disti軟體開發t。

19. 用union all 代替 union,資料庫執行union操作,首先先分別執行union兩端的查詢,將其放在臨時表中,然後在對其進行排序,過濾重復的記錄。
當已知的業務邏輯決定query A和query B中不會有重復記錄時,應該用union all代替union,以提高查詢效率。

數據更新的效率
1. 在一個事物中,對同一個表的多個insert語句應該集中在一起執行。
2. 在一個業務過程中,盡量的使insert,update,delete語句在業務結束前執行,以減少死鎖的可能性。

資料庫物理規劃的效率

為了避免I/O的沖突,我們在設計資料庫物理規劃時應該遵循幾條基本的原則(以ORACLE舉例):
?? table和index分離:table和index應該分別放在不同的tablespace中。

?? Rollback Segment的分離:Rollback Segment應該放在獨立的Tablespace中。

?? System Tablespace的分離:System Tablespace中不允許放置任何用戶的object。(mssql中primary filegroup中不允許放置任何用戶的object)

?? Temp Tablesace的分離:建立單獨的Temp Tablespace,並為每個user指定default Temp Tablespace

??避免碎片:但segment中出現大量的碎片時,會導致讀數據時需要訪問的block數量的增加。對經常發生DML操作的segemeng來說,碎片是不能完全避免的。所以,我們應該將經常做DML操作的表和很少發生變化的表分離在不同的Tablespace中。

當我們遵循了以上原則後,仍然發現有I/O沖突存在,我們可以用數據分離的方法來解決。
?? 連接Table的分離:在實際應用中經常做連接查詢的Table,可以將其分離在不同的Taclespace中,以減少I/O沖突。

?? 使用分區:對數據量很大的Table和Index使用分區,放在不同的Tablespace中。

在實際的物理存儲中,建議使用RAID。日誌文件應放在單獨的磁碟中。

7. 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數據類型, 你可以索引幾乎
所有的列. 通常, 在大型表中使用索引特別有效. 當然,你也會發現, 在掃描小
表時,使用索引同樣能提高效率. 雖然使用索引能得到查詢效率的提高,但是我們
也必須注意到它的代價. 索引需要空間來存儲,也需要定期維護, 每當有記錄在
表中增減或索引列被修改時, 索引本身也會被修改. 這意味著每條記錄的INSERT
, DELETE , UPDATE將為此多付出4 , 5 次的磁碟I/O . 因為索引需要額外的存
儲空間和處理,那些不必要的索引反而會使查詢反應時間變慢.。定期的重構索引
是有必要的.:
ALTER INDEX <INDEXNAME> REBUILD <TABLESPACENAME>
(18)用EXISTS替換DISTINCT:
當提交一個包含一對多表信息(比如部門表和雇員表)的查詢時,避免在
SELECT子句中使用DISTINCT. 一般可以考慮用EXIST替換, EXISTS 使查詢更為迅
速,因為RDBMS核心模塊將在子查詢的條件一旦滿足後,立刻返回結果. 例子:
(低效): SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D , EMP E
WHERE D.DEPT_NO = E.DEPT_NO (高效): SELECT DEPT_NO,DEPT_NAME FROM DEPT
D WHERE EXISTS ( SELECT 『X' FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO);
(19) sql語句用大寫的;因為oracle總是先解析sql語句,把小寫的字母轉換成大寫的再執行
(20)在java代碼中盡量少用連接符「+」連接字元串!

8. 怎麼用delphi+SQL語句實現sql里數據減少

有幾種方法可以實現,一種是當你在edit2中輸入數量,按確定後,執行
update 庫存表 set 數量=數量-strtoint(trim(edit2.text);
還有一種就是在出倉表中創建insert觸發器,當有新的出倉記錄時會自動減少相應的庫存

9. SQL語句能直接操作一張表的某個值加1,或者減1么具體語句應該怎麼寫

sql語句將一個表的某個值加1或減1,直接用update語句即可。

工具:mysql 5.6

步驟:

1、如圖,student表中有如下數據:

10. 為什麼靜態sql語句會減少軟解析

深入shared pool

解析SQL語句

生成執行計劃

中間考慮的因素很多,包括訪問的對象的存在、許可權、等等

執行SQL語句

解析的過程(生成最優執行計劃)是一個耗費資源的過程,隨著用戶的並發數量的增加。資料庫的性能也會降低的很快。

ORCLE對解析的執行
1、ORACLE將SQL語句分成為兩個部分:靜態部分+動態部分
2、靜態部分:SQL 語句的關鍵詞(所涉及的表名稱、列名稱、等)
3、動態部分:字面值(表裡面的表數據,例如 where name=『xkj』中的xkj)
靜態部分是有限的、動態部分是無限的

綁定變數:實現SQL共享(靜態部分),減少解析。在實際中,不同的SQL語句的靜態部分的重復率非常的高。實際上,動態部分對SQL語句的解析的影響可以忽略不計
通過使用綁定變數,用來提高SQL語句的緩存命中率(減少解析次數、減少sql緩存)

declare
v1 varchar2(10);
n1 int;
begin
n1:=1
select salary into v1 from test where id=n1;
end;

在上面的SQL語句中,使用了綁定變數n1,在解析的時候,使用的綁定變數。執行的時候,將字面值傳入語句中。因此這樣SQL語句的命中率將會提高。

ORCLE將解析過的SQL語句緩存在shared pool中,碰到相同的SQL語句再次執行的時候,ORACLE直接使用已經解析過的執行計劃。
Shared pool緩存內容:SQL語句、執行計劃、PL/SQL代碼、PL/SQL機器碼等

Shared pool細分
1、庫緩存:最近執行的SQL語句、存儲過程、函數、解析樹、執行計劃,最活躍部分
2、數據字典緩存:SQL執行過程中涉及的數據字典
遞歸調用:shared pool為生成執行計劃,又進行了很多別的調用(如查詢數據字典)