1. sql 如何用臨時表優化性能
InnoDB 類型的臨時表存在的潛在問題
盡管使用 InnoDB 是性能最佳的,但可能會出現新的潛在問題。在某些特定情況下,您可能會出現磁碟耗盡和伺服器中斷。
與資料庫中的任何其他 InnoDB 表一樣,臨時表具有自己的表空間文件。新文件與通用表空間一起位於數據目錄中,名稱為 ibtmp1。它存儲所有 tmp 表。不運行手動運行 OPTIMIZE TABLE,表空間文件就會不斷增長。如果你不能使用 OPTIMIZE,那麼唯一能將 ibtmp1 大小縮小為零的方法,就是重新啟動伺服器。幸運的是,即使文件無法減小,在執行查詢後,臨時表也會自動刪除,表空間可回收使用。現在,我們想一想以下情境:
存在未優化的查詢,需要在磁碟上創建非常大的的臨時表
存在優化的查詢,但他們正在磁碟上創建非常大的臨時表,因為你正在對此數據集進行計算(統計,分析)
高並發連接時,運行相同的查詢,伴隨臨時表的創建
沒有很多可用空間
- 在這些情況下,文件 ibtmp1 大大增加,很容易耗盡可用空間。這種情況每天發生幾次,並且必須重啟伺服器才能完全縮小 ibtmp1 表空間。使用不可收縮的文件可以輕松耗盡磁碟空間!
- 雖然可以暫時解決問題,但這不是最佳解決方案。實際上,您可以通過逐步增加磁碟大小,來猜測具體需要的空間。如果環境位於雲中,或者在非常大的虛擬平台,這很容易實現。但是使用這種解決方案,您可能會面臨不必要的開支。您還可以通過設置以下配置變數將 ibtmp1 文件移動到專用大型磁碟上: [mysqld] innodb_temp_data_file_path = ../../tmp/ibtmp1:12M:autoextend
- 例如: [mysqld] innodb_temp_data_file_path = ibtmp1:12M:autoextend:max:10G
- 退回 MyISAM 將臨時表存儲在磁碟上
- internal_tmp_disk_storage_engine = MYISAM
- 由於變數是動態的,您也可以在運行時設置它: SET GLOBAL internal_tmp_disk_storage_engine = MYISAM;
- 回到 MyISAM,您將大大降低寫滿磁碟空間的可能性。實際上,臨時表將創建到不同的文件中,並在查詢結束時立即刪除。
- 在將存儲引擎退回到 MyISAM 以減輕中斷發生後,必須花時間分析查詢。目標是減小磁碟上臨時表的大小。本文的目的不是解釋如何調查查詢,而是可以依賴慢速日誌,像 pt-query-digest 和 EXPLAIN 這樣的工具。一些技巧:
在表上創建缺少的索引
如果不需要,可以在查詢中添加更多過濾條件以更少收集的數據
重寫查詢以優化執行計劃
可以在應用程序中使用隊列管理器來序列化它們的執行或減少並發性
那麼,如何避免磁碟耗盡和中斷呢?
簡單的解決方案:使用更大的磁碟
需要重啟 MySQL 。注意,必須將路徑指定為相對於數據目錄。
設置 ibtmp1 大小的上限
在這種情況下,文件不能超過 10GB。可以降低宕機概率,但也是一個危險的解決方案。當數據文件達到最大值時,會查詢失敗並顯示一個錯誤,提示表已滿。
這個解決方案似乎違反直覺,但它可能是快速避免中斷的最佳方法,並保證使用所有需要的臨時表。
雖然總是有可能看到相同的問題,以防你可以在同一時間運行查詢或非常接近。在我的實際案例中,這是避免所有中斷的解決方案。
優化你的查詢
但希望在所有優化之後,您可以返回將臨時存儲引擎設置為 InnoDB 以獲得更好的性能。
結論
有時這些改進會產生意想不到的副作用。用於磁碟上臨時表的 InnoDB 存儲引擎是一個很好的改進,但在某些特定情況下,例如,如果您有未優化查詢和很少的可用空間,則可能因「磁碟已滿」錯誤而中斷。將 tmp 存儲引擎退回到 MyISAM 是避免中斷的最快方法,但是為了返回到 InnoDB,查詢的優化是更重要的事情。更大或專用的磁碟也可能有所幫助。但這是一個微不足道的建議。
2. 如何提高上百萬級記錄MySQL資料庫查詢速度
先安裝 Apache Spark,查詢資料庫的速度可以提升10倍。
在已有的 MySQL 伺服器之上使用 Apache Spark (無需將數據導出到 Spark 或者 Hadoop 平台上),這樣至少可以提升 10 倍的查詢性能。使用多個 MySQL 伺服器(復制或者 Percona XtraDB Cluster)可以讓我們在某些查詢上得到額外的性能提升。你也可以使用 Spark 的緩存功能來緩存整個 MySQL 查詢結果表。
思路很簡單:Spark 可以通過 JDBC 讀取 MySQL 上的數據,也可以執行 SQL 查詢,因此我們可以直接連接到 MySQL 並執行查詢。那麼為什麼速度會快呢?對一些需要運行很長時間的查詢(如報表或者BI),由於 Spark 是一個大規模並行系統,因此查詢會非常的快。MySQL 只能為每一個查詢分配一個 CPU 核來處理,而 Spark 可以使用所有集群節點的所有核。在下面的例子中,我們會在 Spark 中執行 MySQL 查詢,這個查詢速度比直接在 MySQL 上執行速度要快 5 到 10 倍。
另外,Spark 可以增加「集群」級別的並行機制,在使用 MySQL 復制或者 Percona XtraDB Cluster 的情況下,Spark 可以把查詢變成一組更小的查詢(有點像使用了分區表時可以在每個分區都執行一個查詢),然後在多個 Percona XtraDB Cluster 節點的多個從伺服器上並行的執行這些小查詢。最後它會使用map/rece 方式將每個節點返回的結果聚合在一起形成完整的結果。
3. SQL臨時表使用
1、創建方法:
方法一:
create table TempTableName
或
select [欄位1,欄位2,...,] into TempTableName from table
方法二:
create table tempdb.MyTempTable(Tid int)
說明:
(1)、臨時表其實是放在資料庫tempdb里的一個用戶表;
(2)、TempTableName必須帶「#」,「#"可以是一個或者兩個,以#(局部)或##(全局)開頭的表,這種表在會話期間存在,會話結束則自動刪除;
(3)、如果創建時不以#或##開頭,而用tempdb.TempTable來命名它,則該表可在資料庫重啟前一直存在。
2、手動刪除
drop table TempTableName
說明:
DROP TABLE 語句顯式除去臨時表,否則臨時表將在退出其作用域時由系統自動除去:
(1)、當存儲過程完成時,將自動除去在存儲過程中創建的本地臨時表。由創建表的存儲過程執行的所有嵌套存儲過程都可以引用此表。但調用創建此表的存儲過程的進程無法引用此表;
(2)、所有其它本地臨時表在當前會話結束時自動除去;
(3)、全局臨時表在創建此表的會話結束且其它任務停止對其引用時自動除去。任務與表之間的關聯只在單個Transact-SQL語句的生存周期內保持。換言之,當創建全局臨時表的會話結束時,最後一條引用此表的Transact-SQL語句完成後,將自動除去此表。
4. sql數據查詢,把多次查詢結果合並插入到一個臨時表裡但是速度比較慢如何解決呢求教!
你合並的時候使用的是union還是union all,如果是union的話那麼效率是相當低的,你還是採用union all,最後這張臨時的結果有可能有重復的,你在把裡面重復結果刪除到你滿意
5. sql server 存儲過程 臨時表 越來越慢
1、盡量優化語句,盡量少用游標。
2、修改較為常用的表要注意,最好先在臨時表中作好運算和其它處理,最後在修改這些表,以免較慢的存儲過程長時間鎖定表記錄,影響數據正常使用。
3、將連接超時和命令超時適當擴大,以免超時錯誤。
6. SQL 臨時表創建索引會提高效率嗎
只要你索引設置合理,當然會提升效率,其實臨時表你也可以理解為存儲在TempDB資料庫中的物理表。
我在做復雜業務流程處理時,經常用到臨時表,這樣就能避免對原始大數據表的頻繁檢索,明顯對速度有提升
7. 怎麼樣增快sql語句
T-SQL腳本優化技巧:
1)對於SELECT/UPDATE語句必須顯示的定義所有的列,避免使用星號。
2)在執行SELECT/INSERT/UPDATE/DELETE語句時,請考慮執行規劃的重用,盡量考慮用SP-EXECUTESQL存儲過程。
3)優先使用 SELECT...INTO,然後使用 INSERT...SELECT,以避免大量死鎖。
4)如果需要刪除所有的數據,用TRUNCATE TABLE 代替DELETE 。
5)避免使用DISTINCT 語句。
6)如果你需要有限的記錄,通過TOP N代替SET ROWCOUNT來控制排序取值。
7)避免使用SARGABLE的語句在WHERE子句,比如: OR, <>, !=, !<, >!, IS NULL, NOT, NOT IN, NOT LIKE 和LIKE,因為這些操作很難利用已知的索引。
8)避免使用NOT IN,可以採用IN,EXISTS NOT EXISTS和LEFT JOIN 加空值判斷
--NOT EXISTS, 效率最高 SELECT a.hdr_key
FROM hdr_tbl a
WHERE NOT EXISTS (SELECT * FROM dtl_tbl b WHERE a.hdr_key = b.hdr_key) --LEFT JOIN SELECT a.hdr_key
FROM hdr_tbl a
LEFT JOIN dtl_tbl b ON a.hdr_key = b.hdr_key
WHERE b.hdr_key IS NULL --NOT IN ,效率最低 SELECT hdr_key
FROM hdr_tbl
WHERE hdr_key NOT IN (SELECT hdr_key FROM dtl_tbl) 9)使用EXISTS判斷記錄是否存在。
--不好的寫法: IF (SELECT COUNT(*) FROM table_name WHERE column_name = 'xxx') --正確的寫法: IF EXISTS (SELECT * FROM table_name WHERE column_name = 'xxx') 10)避免在GROUP BY中使用HAVING 語句。
11)GROUP BY的語句要盡量簡單,不要進行GROUP BY語句的嵌套,避免在GROUP BY中包含多餘的列
考慮在GROUP BY的列,進行ORDER BY排序,特別在多用戶的環境下。
12)如果需要在一個包含JOIN的SELECT語句進行GROUP BY,請考慮用子查詢代替JOIN. 如果必須使用GROUP BY, GROUP BY 的應該列在同一張表。
13)如果WHERE條件語句有多個AND條件,請確保至少有一個列有索引,如果沒有可以建立多列復合INDEX。
14)對於SQL 無法執行自動優化的WHERE條件語句,可以通過HINTS顯示的制定INDEX來提高查詢的效率。
--可能不好的寫法: SELECT * FROM tblTaskProcessesWHERE nextprocess = 1 AND processid IN (8,32,45) --正確的寫法: SELECT * FROM tblTaskProcesses (INDEX = IX_ProcessID)WHERE nextprocess = 1 AND processid IN (8,32,45) 15)盡可能避免在WHERE條件語句中使用函數計算。
--不好的寫法: WHERE SUBSTRING(firstname,1,1) = 'm' --正確的寫法: WHERE firstname like 'm%' 16)在WHERE條件語句中,避免在函數中包列,如果無法避免,請考慮在該列建立INDEX。
--不好的寫法: SELECT member_number, first_name, last_name
FROM members
WHERE DATEDIFF(yy,datofbirth,GETDATE()) > 21 -- 正確的寫法: SELECT member_number, first_name, last_name
FROM members
WHERE dateofbirth < DATEADD(yy,-21,GETDATE()) 17)在WHERE條件語句中,避免使用NOT 。
--不好的寫法: WHERE NOT column_name > 5 --正確的寫法: WHERE column_name <= 5 18)在WHERE條件語句中,推薦使用10位的日期函數。
--正確的寫法: SELECT * FROM Northwind.dbo.Orders WHERE OrderDate > '12/31/1997'--不好的寫法: SELECT * FROM Northwind.dbo.Orders WHERE OrderDate > '12/31/97' 19)避免使用UNION,而是用UNION ALL 。
20)使用 SQL-92 標准連接句法,為了提高性能,應優先使用連接,然後使用子查詢或嵌套查詢,表之間的連接使用INNER JOIN,LEFT JOIN 和RIGHT JOIN,不使用CROSS JOIN和多列表方式.。
21)多表關聯避免超過5個,可以通過臨時表(表變數),簡化復雜的關聯。
存儲過程的開發和優化技巧:1)避免使用觸發器TRIGGER,考慮用存儲過程代替觸發器
——與臨時表一樣,游標並不是不可使用。對小型數據集使用FAST_FORWARD 游標通常要優於其他逐行處理方法,尤其是在必須引用幾個表才能獲得所需的數據時。在結果集中包括「合計」的常式通常要比使用游標執行的速度快。如果開發時 間允許,基於游標的方法和基於集的方法都可以嘗試一下,看哪一種方法的效果更好。2)考慮用UDF代替存儲過程
——使用表值 UDF 時要小心,因為在變數(而不是常量)中傳遞某個參數時,如果在 WHERE 子句中使用該參數,會導致表掃描。還要避免在一個查詢中多次使用相同的表值 UDF。但是,表值 UDF 確實具有某些非常方便的動態編譯功能。3)對於頻繁調用的存儲過程,考慮用SP_RECOMPILE重新編譯
4)使用輸出語句代替返回整個數據集,輸出語句的執行效率會更加高效
5)在存儲過程的頭部使用SET NOCOUNT ON, 通過@@ROWCOUNT來控制,這樣可以減少網路流量和避免潛在的問題, 而在結束時設置 SET NOCOUNT OFF.
6)不使用SP_作為存儲過程的名稱,建議用USP_,這個會影響資料庫的執行時間.
7)盡可能使用臨時表而使用表變數,表變數可以減少上鎖和重新編譯的次數並且表變數不使用TEMPDB的空間,而是全部使用內存來處理數據.
8)先在常式中創建臨時表,最後再顯式刪除臨時表。將 DDL 與 DML 語句混合使用有助於處理額外的重新編譯活動
9)盡可能不要在流程式控制制語句中使用臨時表,比如:IF .. ELSE, WHILE
10)避免在事務中進行賦值和復雜計算,
--不好的寫法: Create procere proc_1 As Begin Begin transaction -- step 1 verify the data -- step 2 perform calculations -- step 3 get default variable values (date, user info) -- update/insert records commit end --不好的寫法: Create procere proc_1 As Begin -- step 1 verify the data -- step 2 make calculations -- step 3 get default variable values (date, user info) Begin transaction -- update/insert records commit end 上面的一些優化規則只是一般原則,在某些特殊情況下可能會有所差別,如果需要分析T-SQL的性能,可以通過查詢分析器的CTRL+L 顯示執行規劃進行分析,也可以通過 SET STATISTICS PROFILE ON進行分析.
8. 如何提高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 子句中使用參數,也會導致全表掃描。因為SQL只有在運行時才會解析局部變數,但優化程序不能將訪問計劃的選擇推遲到運行時;它必須在編譯時進行選擇。然而,如果在編譯時建立訪問計劃,變數的值還是未知的,因而無法作為索引選擇的輸入項。如下面語句將進行全表掃描:
select id from t where num=@num
可以改為強制查詢使用索引:
select id from t with(index(索引名)) where num=@num
8.應盡量避免在 where 子句中對欄位進行表達式操作,這將導致引擎放棄使用索引而進行全表掃描。如:
select id from t where num/2=100
應改為:
select id from t where num=100*2
9.應盡量避免在where子句中對欄位進行函數操作,這將導致引擎放棄使用索引而進行全表掃描。如:
select id from t where substring(name,1,3)='abc' // oracle總有的是substr函數。
select id from t where datediff(day,createdate,'2005-11-30')=0 //查過了確實沒有datediff函數。
應改為:
select id from t where name like 'abc%'
select id from t where createdate>='2005-11-30' and createdate<'2005-12-1' //
oracle 中時間應該把char 轉換成 date 如: createdate >= to_date('2005-11-30','yyyy-mm-dd')
10.不要在 where 子句中的「=」左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引。
11.在使用索引欄位作為條件時,如果該索引是復合索引,那麼必須使用到該索引中的第一個欄位作為條件時才能保證系統使用該索引,否則該索引將不會被使用,並且應盡可能的讓欄位順序與索引順序相一致。
12.不要寫一些沒有意義的查詢,如需要生成一個空表結構:
select col1,col2 into #t from t where 1=0
這類代碼不會返回任何結果集,但是會消耗系統資源的,應改成這樣:
create table #t(...)
13.很多時候用 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)
14.並不是所有索引對查詢都有效,SQL是根據表中數據來進行查詢優化的,當索引列有大量數據重復時,SQL查詢可能不會去利用索引,如一表中有欄位sex,male、female幾乎各一半,那麼即使在sex上建了索引也對查詢效率起不了作用。
15.索引並不是越多越好,索引固然可以提高相應的 select 的效率,但同時也降低了 insert 及 update 的效率,因為 insert 或 update 時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有必要。
16.應盡可能的避免更新 clustered 索引數據列,因為 clustered 索引數據列的順序就是表記錄的物理存儲順序,一旦該列值改變將導致整個表記錄的順序的調整,會耗費相當大的資源。若應用系統需要頻繁更新 clustered 索引數據列,那麼需要考慮是否應將該索引建為 clustered 索引。
17.盡量使用數字型欄位,若只含數值信息的欄位盡量不要設計為字元型,這會降低查詢和連接的性能,並會增加存儲開銷。這是因為引擎在處理查詢和連接時會逐個比較字元串中每一個字元,而對於數字型而言只需要比較一次就夠了。
18.盡可能的使用 varchar/nvarchar 代替 char/nchar ,因為首先變長欄位存儲空間小,可以節省存儲空間,其次對於查詢來說,在一個相對較小的欄位內搜索效率顯然要高些。
19.任何地方都不要使用 select * from t ,用具體的欄位列表代替「*」,不要返回用不到的任何欄位。
20.盡量使用表變數來代替臨時表。如果表變數包含大量數據,請注意索引非常有限(只有主鍵索引)。
21.避免頻繁創建和刪除臨時表,以減少系統表資源的消耗。
22.臨時表並不是不可使用,適當地使用它們可以使某些常式更有效,例如,當需要重復引用大型表或常用表中的某個數據集時。但是,對於一次性事件,最好使用導出表。
23.在新建臨時表時,如果一次性插入數據量很大,那麼可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果數據量不大,為了緩和系統表的資源,應先create table,然後insert。
24.如果使用到了臨時表,在存儲過程的最後務必將所有的臨時表顯式刪除,先 truncate table ,然後 drop table ,這樣可以避免系統表的較長時間鎖定。
25.盡量避免使用游標,因為游標的效率較差,如果游標操作的數據超過1萬行,那麼就應該考慮改寫。
26.使用基於游標的方法或臨時表方法之前,應先尋找基於集的解決方案來解決問題,基於集的方法通常更有效。
27.與臨時表一樣,游標並不是不可使用。對小型數據集使用 FAST_FORWARD 游標通常要優於其他逐行處理方法,尤其是在必須引用幾個表才能獲得所需的數據時。在結果集中包括「合計」的常式通常要比使用游標執行的速度快。如果開發時間允許,基於游標的方法和基於集的方法都可以嘗試一下,看哪一種方法的效果更好。
28.在所有的存儲過程和觸發器的開始處設置 SET NOCOUNT ON ,在結束時設置 SET NOCOUNT OFF 。無需在執行存儲過程和觸發器的每個語句後向客戶端發送 DONE_IN_PROC 消息。
29.盡量避免大事務操作,提高系統並發能力。
30.盡量避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理。
9. 如何讓有臨時表的SQL語句執行計劃效率高
這要看臨時表的數據量啊,如果你臨時表很大,採用何種執行計劃都一樣慢的,難道數據大的時候,你對臨時表索引嗎 這樣也不現實啊 ,所以根本問題還是從業務層面限制臨時表的數據量。