當前位置:首頁 » 編程語言 » sql數據讀寫速度慢
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

sql數據讀寫速度慢

發布時間: 2022-05-12 01:49:53

1. sql2000訪問速度慢

SQL Server資料庫查詢速度慢的原因有很多,常見的有以下幾種:

1、沒有索引或者沒有用到索引(這是查詢慢最常見的問題,是程序設計的缺陷)

2、I/O吞吐量小,形成了瓶頸效應。

3、沒有創建計算列導致查詢不優化。

4、內存不足

5、網路速度慢

6、查詢出的數據量過大(可以採用多次查詢,其他的方法降低數據量)

7、鎖或者死鎖(這也是查詢慢最常見的問題,是程序設計的缺陷)

8、sp_lock,sp_who,活動的用戶查看,原因是讀寫競爭資源。

9、返回了不必要的行和列

10、查詢語句不好,沒有優化

●可以通過以下方法來優化查詢 :

1、把數據、日誌、索引放到不同的I/O設備上,增加讀取速度,以前可以將Tempdb應放在RAID0上,SQL2000不在支持。數據量(尺寸)越大,提高I/O越重要。

2、縱向、橫向分割表,減少表的尺寸(sp_spaceuse)

3、升級硬體

4、根據查詢條件,建立索引,優化索引、優化訪問方式,限制結果集的數據量。注意填充因子要適當(最好是使用默認值0)。索引應該盡量小,使用位元組數小的列建索引好(參照索引的創建),不要對有限的幾個值的欄位建單一索引如性別欄位。

5、提高網速。

6、擴大伺服器的內存,Windows 2000和SQL server 2000能支持4-8G的內存。

配置虛擬內存:虛擬內存大小應基於計算機上並發運行的服務進行配置。運行 Microsoft SQL Server? 2000時,可考慮將虛擬內存大小設置為計算機中安裝的物理內存的1.5倍。如果另外安裝了全文檢索功能,並打算運行Microsoft搜索服務以便執行全文索引和查詢,可考慮:將虛擬內存大小配置為至少是計算機中安裝的物理內存的3倍。將SQL Server max server memory伺服器配置選項配置為物理內存的1.5倍(虛擬內存大小設置的一半)。

7、增加伺服器CPU個數;但是必須 明白並行處理串列處理更需要資源例如內存。使用並行還是串列程是MsSQL自動評估選擇的。單個任務分解成多個任務,就可以在處理器上運行。例如耽擱查詢 的排序、連接、掃描和GROUP BY字句同時執行,SQL SERVER根據系統的負載情況決定最優的並行等級,復雜的需要消耗大量的CPU的查詢最適合並行處理。但是更新操作UPDATE,INSERT, DELETE還不能並行處理。

8、如果是使用like進行查詢的話,簡單的使用index是不行的,但是全文索引,耗空間。 like ''a%'' 使用索引 like ''%a'' 不使用索引用 like ''%a%'' 查詢時,查詢耗時和欄位值總長度成正比,所以不能用CHAR類型,而是VARCHAR。對於欄位的值很長的建全文索引。

9、DB Server 和APPLication Server 分離;OLTP和OLAP分離

10、分布式分區視圖可用於實現資料庫伺服器聯合體。

聯合體是一組分開管理的伺服器,但它們相互協作分擔系統的處理負荷。這種通過分區數據形成資料庫伺服器聯合體的機制能夠擴大一組伺服器,以支持大型的多層 Web 站點的處理需要。有關更多信息,參見設計聯合資料庫伺服器。(參照SQL幫助文件''分區視圖'')

a、在實現分區視圖之前,必須先水平分區表

b、 在創建成員表後,在每個成員伺服器上定義一個分布式分區視圖,並且每個視圖具有相同的名稱。這樣,引用分布式分區視圖名的查詢可以在任何一個成員伺服器上 運行。系統操作如同每個成員伺服器上都有一個原始表的復本一樣,但其實每個伺服器上只有一個成員表和一個分布式分區視圖。數據的位置對應用程序是透明的。

11、重建索引 DBCC REINDEX ,DBCC INDEXDEFRAG,收縮數據和日誌 DBCC SHRINKDB,DBCC SHRINKFILE. 設置自動收縮日誌.對於大的資料庫不要設置資料庫自動增長,它會降低伺服器的性能。

在T-sql的寫法上有很大的講究,下面列出常見的要點:首先,DBMS處理查詢計劃的過程是這樣的:

1、 查詢語句的詞法、語法檢查

2、 將語句提交給DBMS的查詢優化器

3、 優化器做代數優化和存取路徑的優化

4、 由預編譯模塊生成查詢規劃

5、 然後在合適的時間提交給系統處理執行

6、 最後將執行結果返回給用戶。

其次,看一下SQL SERVER的數據存放的結構:一個頁面的大小為8K(8060)位元組,8個頁面為一個盤區,按照B樹存放。

2. 最近我的資料庫(sql)查詢速度很慢,這是什麼原因

查詢慢是和表結構,語句,系統等相關的 建索引等方法都可以改善表結構, 另外如果返回數據量很大,當然會慢,所以你盡量查詢相對有用的數據 再就是查詢語句了 比如用in查詢沒有jion查詢快,還有 between 改成 > <會快 再還有,用子查詢也會慢很多, 如果是一些很復雜的查詢,可以改用存儲過程會好點,有時用臨時表會慢但,從海量數據中查詢取數進行子查詢又不如用臨時錶快,不同的問題用不同的解決方法,看你要哪種了,單看你的問題無法直接判斷。 不過,優化查詢句是關鍵的了。

3. SQL 語句執行感覺很慢,怎麼回事

到這個數量級的全部更新,肯定會很慢。
第一。你的記錄不一定在同一個partition,
第二。不明白為什麼那麼多人建議你建索引,你建的索引越多,你的更新速度越慢,因為你更新記錄的同時,還有更新索引。
第三。你必須知道更新速度慢的瓶頸在哪裡。是讀寫太多,還是內存不夠,還是CUP不夠快,然後對症下葯。

下面介紹兩個簡單的辦法,也許有效:
第一:
把這個100W行的表縱向劈成兩個,用外鍵關系連接,一個裝小的,經常改變的數據比如ID,外鍵,狀態值,時間等,另一個裝大的,不經常改變的數據,比如很長的字元串,xml,text 等。
這樣更新時操作小的這個表,可以大大節約內存和CPU 開銷,降低磁碟操作。
壞處就是查詢時會慢些。
第二:
把這100W行橫向切成很多個表,比如每個月的記錄裝在一個表裡,這樣每個表的記錄數可能只有幾萬,查詢,更新都會快很多。
壞處是查詢,更新都不如原來好寫。

4. 用JDBC連接 SQL Server 2012 資料庫查詢速度慢怎麼解決

SQL
Server查詢速度慢的原因有很多,常見的有以下幾種:
1、沒有索引或者沒有用到索引(這是查詢慢最常見的問題,是程序設計的缺陷)
2、I/O吞吐量小,形成了
瓶頸效應

3、沒有創建計算列導致查詢不優化。
4、
內存不足

5、
網路速度

6、查詢出的數據量過大(可以採用多次查詢,其他的方法降低數據量)
7、鎖或者
死鎖
(這也是查詢慢最常見的問題,是程序設計的缺陷)
8、sp_lock,sp_who,活動的用戶查看,原因是讀寫
競爭資源

5. 如何解決SQL Server資料庫查詢速度慢

�緯閃似烤斃вΑ� 3、沒有創建計算列導致查詢不優化。 4、內存不足5、網路速度慢6、查詢出的數據量過大(可以採用多次查詢,其他的方法降低數據量) 7、鎖或者死鎖(這也是查詢慢最常見的問題,是程序設計的缺陷) 8、sp_lock,sp_who,活動的用戶查看,原因是讀寫競爭資源。 9、返回了不必要的行和列10、查詢語句不好,沒有優化 可以通過以下方法來優化查詢 : 1、把數據、日誌、索引放到不同的I/O設備上,增加讀取速度,以前可以將Tempdb應放在RAID0上,SQL2000不在支持。數據量(尺寸)越大,提高I/O越重要。 2、縱向、橫向分割表,減少表的尺寸(sp_spaceuse) 3、升級硬體 4、根據查詢條件,建立索引,優化索引、優化訪問方式,限制結果集的數據量。注意填充因子要適當(最好是使用默認值0)。索引應該盡量小,使用位元組數小的列建索引好(參照索引的創建),不要對有限的幾個值的欄位建單一索引如性別欄位。 5、提高網速。 6、擴大伺服器的內存,Windows 2000和SQL server 2000能支持4-8G的內存。 配置虛擬內存:虛擬內存大小應基於計算機上並發運行的服務進行配置。運行 Microsoft SQL Server? 2000時,可考慮將虛擬內存大小設置為計算機中安裝的物理內存的1.5倍。如果另外安裝了全文檢索功能,並打算運行Microsoft搜索服務以便執行全文索引和查詢,可考慮:將虛擬內存大小配置為至少是計算機中安裝的物理內存的3倍。將SQL Server max server memory伺服器配置選項配置為物理內存的1.5倍(虛擬內存大小設置的一半)。 7、增加伺服器CPU個數;但是必須 明白並行處理串列處理更需要資源例如內存。使用並行還是串列程是MsSQL自動評估選擇的。單個任務分解成多個任務,就可以在處理器上運行。例如耽擱查詢 的排序、連接、掃描和GROUP BY字句同時執行,SQL SERVER根據系統的負載情況決定最優的並行等級,復雜的需要消耗大量的CPU的查詢最適合並行處理。但是更新操作UPDATE,INSERT, DELETE還不能並行處理。 8、如果是使用like進行查詢的話,簡單的使用index是不行的,但是全文索引,耗空間。 like ''a%'' 使用索引 like ''%a'' 不使用索引用 like ''%a%'' 查詢時,查詢耗時和欄位值總長度成正比,所以不能用CHAR類型,而是VARCHAR.對於欄位的值很長的建全文索引。 9、DB Server 和APPLication Server 分離;OLTP和OLAP分離 10、分布式分區視圖可用於實現資料庫伺服器聯合體。 聯合體是一組分開管理的伺服器,但它們相互協作分擔系統的處理負荷。這種通過分區數據形成資料庫伺服器聯合體的機制能夠擴大一組伺服器,以支持大型的多層 Web 站點的處理需要。有關更多信息,參見設計聯合資料庫伺服器。(參照SQL幫助文件''分區視圖'') a、在實現分區視圖之前,必須先水平分區表 b、在創建成員表後,在每個成員伺服器上定義一個分布式分區視圖,並且每個視圖具有相同的名稱。這樣,引用分布式分區視圖名的查詢可以在任何一個成員伺服器上 運行。系統操作如同每個成員伺服器上都有一個原始表的復本一樣,但其實每個伺服器上只有一個成員表和一個分布式分區視圖。數據的位置對應用程序是透明的。 11、重建索引 DBCC REINDEX ,DBCC INDEXDEFRAG,收縮數據和日誌 DBCC SHRINKDB,DBCC SHRINKFILE. 設置自動收縮日誌。對於大的資料庫不要設置資料庫自動增長,它會降低伺服器的性能。 在T-sql的寫法上有很大的講究,下面列出常見的要點:首先,DBMS處理查詢計劃的過程是這樣的: 1、 查詢語句的詞法、語法檢查2、 將語句提交給DBMS的查詢優化器3、 優化器做代數優化和存取路徑的優化4、 由預編譯模塊生成查詢規劃5、 然後在合適的時間提交給系統處理執行6、 最後將執行結果返回給用戶。 其次,看一下SQL SERVER的數據存放的結構:一個頁面的大小為8K(8060)位元組,8個頁面為一個盤區,按照B樹存放。 12、 Commit和rollback的區別 Rollback:回滾所有的事物。 Commit:提交當前的事物。 沒有必要在動態SQL里寫事物,如果要寫請寫在外面如: begin tran exec(@s) commit trans 或者將動態SQL 寫成函數或者存儲過程。 13、在查詢Select語句中用Where字句限制返回的行數,避免表掃描,如果返回不必要的數據,浪費了伺服器的I/O資源,加重了網路的負擔降低性能。如果表很大,在表掃描的期間將表鎖住,禁止其他的聯接訪問表,後果嚴重。 14、SQL的注釋申明對執行沒有任何影響 15、盡可能不使用游標,它佔用大量的資源。如果需要row-by-row地執行,盡量採用非游標技術,如:在客戶端循環,用臨時表,Table變數,用子查詢,用Case語句等等。 游標可以按照它所支持的提取選項進行分類:只進必須按照從第一行到最後一行的順序提取行。FETCH NEXT 是唯一允許的提取操作,也是默認方式。可滾動性可以在游標中任何地方隨機提取任意行。游標的技術在SQL2000下變得功能很強大,他的目的是支持循環。 有四個並發選項 READ_ONLY:不允許通過游標定位更新(Update),且在組成結果集的行中沒有鎖。 OPTIMISTIC WITH valueS:樂觀並發控制是事務控制理論的一個標准部分。樂觀並發控制用於這樣的情形,即在打開游標及更新行的間隔中,只有很小的機會讓第二個用戶更新某一行。當某個游標以此選項打開時,沒有鎖控制其中的行,這將有助於最大化其處理能力。如果用戶試圖修改某一行,則此行的當前值會與最後一次提取此行時獲取的值進行比較。如果任何值發生改變,則伺服器就會知道其他人已更新了此行,並會返回一個錯誤。如果值是一樣的,伺服器就執行修改。 選擇這個並發選項OPTIMISTIC WITH ROW VERSIONING:此樂觀並發控制選項基於行版本控制。使用行版本控制,其中的表必須具有某種版本標識符,伺服器可用它來確定該行在讀入游標後是否有 所更改。在SQL Server中,這個性能由timestamp數據類型提供,它是一個二進制數字,表示資料庫中更改的相對順序。 每個資料庫都有一個全局當前時間戳值:@@DBTS.每次以任何方式更改帶有 timestamp 列的行時,SQL Server 先在時間戳列中存儲當前的 @@DBTS 值,然後增加 @@DBTS 的值。如果某 個表具有 timestamp 列,則時間戳會被記到行級。伺服器就可以比較某行的當前時間戳值和上次提取時所存儲的時間戳值,從而確定該行是否已更新。伺服器不必比較所有列的值,只需 比較 timestamp 列即可。如果應用程序對沒有 timestamp 列的表要求基於行版本控制的樂觀並發,則游標默認為基於數值的樂觀並發控制。 SCROLL LOCKS 這個選項實現悲觀並發控制。在悲觀並發控制中,在把資料庫的行讀入游標結果集時,應用程序將試圖鎖定資料庫行。在使用伺服器游標時,將行讀入游標時會在其上放置一個更新鎖。如果在事務內打開游標,則該事務更新鎖將一直保持到事務被提交或回滾;當提取下一行時,將除去游標鎖。如果在事務外打開游標,則提取下一行時,鎖就被丟棄。 因此,每當用戶需要完全的悲觀並發控制時,游標都應在事務內打開。更新鎖將阻止任何其它任務獲取更新鎖或排它鎖,從而阻止其它任務更 新該行。然而,更新鎖並不阻止共享鎖,所以它不會阻止其它任務讀取行,除非第二個任務也在要求帶更新鎖的讀取。滾動鎖根據在游標定義的 SELECT 語句中指定的鎖提示,這些游標並發選項可以生成滾動鎖。滾動鎖在提取時在每行上獲取,並保持到下次提取或者游標關閉,以先發生者為准。下次提取時,伺服器為新提取中的行獲取滾動鎖,並釋放上次提取中行的滾動鎖。滾動鎖獨立於事務鎖,並可以保持到一個提交或回滾操作之後。如果提交時關閉游標的選項為關,則COMMIT語句並不關閉任何打開的游標,而且滾動鎖被保留到提交之後,以維護對所提取數據的隔離。所獲取滾動鎖的類型取決於游標並發選項和游標 SELECT 語句中的鎖提示。鎖提示 只讀樂觀數值 指定NOLOCK 提示將使指定了該提示的表在游標內是只讀的。 16、用Profiler來跟蹤查詢,得到查詢所需的時間,找出SQL的問題所在;用索引優化器優化索引 17、注意UNion和UNion all 的區別。UNION all好 18、注意使用DISTINCT,在沒有必要時不要用,它同UNION一樣會使查詢變慢。重復的記錄在查詢里是沒有問題的 19、查詢時不要返回不需要的行、列 20、 用sp_configure ''query governor cost limit''或者SET QUERY_GOVERNOR_COST_LIMIT來限制查詢消耗的資源。當評估查詢消耗的資源超出限制時,伺服器自動取消查詢,在查詢之前就扼殺掉。 SET LOCKTIME設置鎖的時間 21、用select top 100 / 10 Percent 來限制用戶返回的行數或者SET ROWCOUNT來限制操作的行 22、 在SQL2000以前,一般不要用如下的字句: "IS NULL", "<>", "!=", "!>", "!<", "NOT", "NOT EXISTS", "NOT IN", "NOT LIKE", and "LIKE ''%500''",因為他們不走索引全是表掃描。也不要在WHere字句中的列名加函數,如Convert,substring等,如果必須用函數的時 候,創建計算列再創建索引來替代。還可以變通寫法:WHERE SUBSTRING(firstname,1,1) = ''m''改為WHERE firstname like ''m%''(索引掃描),一定要將函數和列名分開。並且索引不能建得太多和太大。NOT IN會多次掃描表,使用EXISTS、NOT EXISTS ,IN , LEFT OUTER JOIN 來替代,特別是左連接,而Exists比IN更快,最慢的是NOT操作。如果列的值含有空,以前它的索引不起作用,現在2000的優化器能夠處理了。相同 的是IS NULL,「NOT", "NOT EXISTS", "NOT IN"能優化她,而」<>「等還是不能優化,用不到索引。 23、使用Query Analyzer,查看SQL語句的查詢計劃和評估分析是否是優化的SQL.一般的20%的代碼占據了80%的資源,我們優化的重點是這些慢的地方。 24、如果使用了IN或者OR等時發現查詢沒有走索引,使用顯示申明指定索引: SELECT * FROM PersonMember (INDEX = IX_Title) WHERE processid IN (『男』,『女』) 25、將需要查詢的結果預先計算好放在表中,查詢的時候再SELECT.這在SQL7.0以前是最重要的手段。例如醫院的住院費計算。 26、MIN() 和 MAX()能使用到合適的索引。 27、 資料庫有一個原則是代碼離數據越近越好,所以優先選擇Default,依次為Rules,Triggers, Constraint(約束如外健主健CheckUNIQUE……,數據類型的最大長度等等都是約束),Procere.這樣不僅維護工作小,編寫程 序質量高,並且執行的速度快。 28、如果要插入大的二進制值到Image列,使用存儲過程,千萬不要用內嵌INsert來插入(不知JAVA 是否)。因為這樣應用程序首先將二進制值轉換成字元串(尺寸是它的兩倍),伺服器受到字元後又將他轉換成二進制值。

6. sql server cube速度慢

1、沒有索引或者沒有用到索引(這是查詢慢最常見的問題,是程序設計的缺陷)
2、I/O吞吐量小,形成了瓶頸效應。
3、沒有創建計算列導致查詢不優化。
4、內存不足
5、網路速度慢
6、查詢出的數據量過大(可以採用多次查詢,其他的方法降低數據量)
7、鎖或者死鎖(這也是查詢慢最常見的問題,是程序設計的缺陷)
8、sp_lock,sp_who,活動的用戶查看,原因是讀寫競爭資源。
9、返回了不必要的行和列
10、查詢語句不好,沒有優化
●可以通過以下方法來優化查詢:
1、把數據、日誌、索引放到不同的I/O設備上,增加讀取速度,以前可以將Tempdb應放在RAID0上,SQL2000不在支持。數據量(尺寸)越大,提高I/O越重要。
2、縱向、橫向分割表,減少表的尺寸(sp_spaceuse)
3、升級硬體
4、根據查詢條件,建立索引,優化索引、優化訪問方式,限制結果集的數據量。注意填充因子要適當(最好是使用默認值0)。索引應該盡量小,使用位元組數小的列建索引好(參照索引的創建),不要對有限的幾個值的欄位建單一索引如性別欄位。
5、提高網速。
6、擴大伺服器的內存,Windows 2000和SQL server 2000能支持4-8G的內存。
配置虛擬內存:虛擬內存大小應基於計算機上並發運行的服務進行配置。運行Microsoft SQL Server?2000時,可考慮將虛擬內存大小設置為計算機中安裝的物理內存的1.5倍。如果另外安裝了全文檢索功能,並打算運行Microsoft搜索服務以便執行全文索引和查詢,可考慮:將虛擬內存大小配置為至少是計算機中安裝的物理內存的3倍。將SQL Server max server memory伺服器配置選項配置為物理內存的1.5倍(虛擬內存大小設置的一半)。
7、增加伺服器CPU個數;但是必須明白並行處理串列處理更需要資源例如內存。使用並行還是串列程是MsSQL自動評估選擇的。單個任務分解成多個任務,就可以在處理器上運行。例如耽擱查詢的排序、連接、掃描和GROUP BY字句同時執行,SQL SERVER根據系統的負載情況決定最優的並行等級,復雜的需要消耗大量的CPU的查詢最適合並行處理。但是更新操作 UPDATE,INSERT,DELETE還不能並行處理。
8、如果是使用like進行查詢的話,簡單的使用index是不行的,但是全文索引,耗空間。like ''a%'' 使用索引 like ''%a'' 不使用索引用 like ''%a%'' 查詢時,查詢耗時和欄位值總長度成正比,所以不能用CHAR類型,而是VARCHAR。對於欄位的值很長的建全文索引。
9、DB Server和APPLication Server 分離;OLTP和OLAP分離
10、分布式分區視圖可用於實現資料庫伺服器聯合體。
聯合體是一組分開管理的伺服器,但它們相互協作分擔系統的處理負荷。這種通過分區數據形成資料庫伺服器聯合體的機制能夠擴大一組伺服器,以支持大型的多層 Web 站點的處理需要。有關更多信息,參見設計聯合資料庫伺服器。
a、在實現分區視圖之前,必須先水平分區表
b、在創建成員表後,在每個成員伺服器上定義一個分布式分區視圖,並且每個視圖具有相同的名稱。這樣,引用分布式分區視圖名的查詢可以在任何一個成員伺服器上運行。系統操作如同每個成員伺服器上都有一個原始表的復本一樣,但其實每個伺服器上只有一個成員表和一個分布式分區視圖。數據的位置對應用程序是透明的。
11、重建索引 DBCC REINDEX ,DBCCINDEXDEFRAG,收縮數據和日誌 DBCC SHRINKDB,DBCC SHRINKFILE. 設置自動收縮日誌.對於大的資料庫不要設置資料庫自動增長,它會降低伺服器的性能

7. SQL Server 2008 SqlDataReader讀取100萬數據超慢,高手幫忙。

這就是執行計劃重編譯和數據緩存

可以分成兩個部分解說,LZ紅包也要給雙份的!

執行計劃簡單的說就是SQL怎麼讀取操作數據。

你這個屬於基於優化的重編譯(optimality-based recompilation---你可以去國外網站查這個關鍵詞),主要是由統計信息發生改變導致(比如記錄十萬百萬的增加)。

如果你想印證的話,可以用profiler跟蹤重編譯事件。


其下你可以用我這個方式測試一下你的SQL。

select
p.usecounts,p.cacheobjtype,p.objtype,t.text
fromsys.dm_exec_cached_plansp
crossapplysys.dm_exec_sql_text(plan_handle)t
wherep.cacheobjtype='CompiledPlan'andt.textlike'%dbo.StrText%'
andt.textnotlike'%dm_exec_cached_plans%'

你把上邊紅框里改成你那個查詢的關鍵字


以上只是測試方法。


第二:數據緩存,這個跟時間有關系,用的是最近最少使用的數據優先清空的原理。

你可以把伺服器內存整到 64G。然後配置一番,基本可以緩存多一些。


原因找到了:具體怎麼做呢?

第一:如果版本可以的,你可以用索引視圖

第二:分頁,這個就是小塊優化了!

第三:我看了一下你這個查詢,可以整合到一個表中,獨立建表

8. 如何解決SQL Server查詢速度緩慢的問題

SQL Server查詢速度慢的原因有很多,常見的有以下幾種: 1、沒有索引或者沒有用到索引(這是查詢慢最常見的問題,是程序設計的缺陷) 2、I/O吞吐量小,形成了瓶頸效應。 3、沒有創建計算列導致查詢不優化。 4、內存不足 5、網路速度慢 6、查詢出的數據量過大(可以採用多次查詢,其他的方法降低數據量) 7、鎖或者死鎖(這也是查詢慢最常見的問題,是程序設計的缺陷) 8、sp_lock,sp_who,活動的用戶查看,原因是讀寫競爭資源。 9、返回了不必要的行和列 10、查詢語句不好,沒有優化

9. 如何解決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 查詢的優化,添加更合適的索引可以避免性能問題:執行計劃使用索引並不意味著就能執行快。

10. 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 查詢的優化,添加更合適的索引可以避免性能問題:執行計劃使用索引並不意味著就能執行快。