當前位置:首頁 » 編程語言 » sql執行計劃不一樣
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

sql執行計劃不一樣

發布時間: 2023-01-10 05:57:04

⑴ 求助:sql執行計劃不同,為什麼

SQL執行計劃本身就是為了找到一種執行最小代價的方式,所以即使是同一SQL語句,在不同數據環境下的執行計劃也可能不同,這很正常

⑵ 同一用戶,同樣的sql,為什麼執行計劃不同

Object owner不一樣,上面的是:CPABYL2,下面的是:CPABG3。 雖然你訪問的同一個伺服器,執行的SQL也一樣,但是用戶不一樣,訪問的表也不一樣。 也就是說你的伺服器上用戶CPABYL2和CPABG3各自有一套table。

⑶ 為什麼SQL在plsql里執行出的時間和執行計劃的不相符

別用PLSQL DEVELOPER ,放在SQL PLUS里執行,就能看出了。

另外,程序開始跟結尾用 dbms_output.putline() 輸出一下系統時間,就能判斷出來執行時間。

要是非用PLSQL DEVELOP ,也可以按F5,看看執行計劃。

如果有 FULL SCAN之類的,就是全表掃描了,估計數據量大的時候,沒有建立或利用上索引,執行會比較慢。

數據量小的時候,要看是不是做跟一個大表的關聯,看看大表關聯是不是用到索引了,用到了也慢不到那裡去,要是沒用到的話,就慢了。

這個問題不好講具體是那裡出的問題,比如CACHE的命中也會影響,前5K都是連續命中,哪就很快,後5K都是間隔命中,哪就多次I/O,肯定就慢!

⑷ 同樣的SQL語句在兩個資料庫上執行,執行計劃差別很大,怎麼回事

執行計劃是根據他的統計信息指定出來的, 但是這個統計信息並不是准確的,只是一個估計值, 當這個值跟實際值差別很大的時候, 執行計劃一定會差很多

⑸ 多表連接查詢和多次單表查詢哪個效率高為什麼

如果數據量小的表,這樣的設計意義不大,而且當然是單錶速度快。若在大數據量情況下,設計非常有意義。在多表連接中注意數據的條目和外健,避免出行大量冗餘數據導致性能下降。下面我以Oracle講講數據查詢的整個過程技術。

由於數據分布到數據塊,在大量數據設計中可以將數據存儲於多個數據塊,在高並發進程的隨機訪問的情況下,能有效減少塊沖突 同樣的數據需要更多的數據塊來存儲,由於數據塊的塊頭元信息大小固定,所以需要更多的空間來存儲塊頭元信息。行長度過大容易導致行連接,從而導致Oracle獲取數據塊的效率降低 ,在行長度固定的前提下,單塊能夠存儲更多的數據行,也就意味著Oracle一次I/O能讀取更多的數據行。適合連續順序讀或者存放大對象數據(如LOB數據) 由於大數據塊可以存放更多的索引葉節點信息,容易引起爭用,所以大數據塊不適合存放索引葉節點信息。

大量數據表的資料庫參數設置DB_FILE_MULTIBLOCK_READ_COUNT表示Oracle一次順序I/O讀操作最多能讀取的數據塊塊數。該參數的默認值隨操作系統的不同而不同。在全表掃描或者索引快速掃描比較多的系統中(如DSS系統),建議將該值設置得較大。但是DB_FILE_MULTIBLOCK_READ_COUNT參數受操作最大單次I/O大小的限制,大多數操作系統單次讀操作的大小不能超過1MB,這也就意味著在8KB數據塊大小的情況下,該參數最大值為128。值得一提的是,該參數的大小還會影響Oracle CBO對執行計劃的評估,如果設成較大值,Oracle的執行計劃傾向於全表掃描。當該參數設置為0或者保持默認時,CBO假設全表掃描時最多能連續讀取8個數據塊。從Oracle 11R2開始,DB_FILE_MULTIBLOCK_READ_COUNT的取值演算法如下:

db_file_multiblock_read_count = min(1048576/db_block_size , db_cache_size/

(sessions * db_block_size))

注意資料庫參數BLOCK_SIZE在設定之後,在資料庫生命周期內不可更改。

當執行SELECT語句時,如果在內存里找不到相應的數據,就會從磁碟讀取進而緩存至LRU末端(冷端),這個過程就叫物理讀。當相應數據已在內存,就會邏輯讀。我物理讀是磁碟讀,邏輯讀是內存讀;內存讀的速度遠比磁碟讀來得快。

下面將本人大數據分區設計截圖,為大家參考學習。

先貼倆圖鎮鎮場。

引言

對於內連接,使用單個查詢是有意義的,因為你只獲得匹配的行。

對於左連接,多個查詢要好得多。


數據說話

看看下面的基準測試:

5個連接的單個查詢

一行5個查詢

注意,我們在兩種情況下得到了 相同的結果 (6 x 50 x 7 x 12 x 90 = 2268000)


總結一下

對於冗餘數據,左連接使用更多的內存。

如果只執行兩個表的連接,那麼內存限制可能沒有那麼糟糕,但通常是三個或更多的表,因此值得進行不同的查詢。


寫在最後

用過Laravel嗎?還記得 Eloquent ORM模型嗎?

不知道有沒有注意到,debug所列印出來的多表聯合查詢,

都是拆分為「單個表查詢」,然後使用PHP處理的。

Happy coding :-)


是做表連接查詢還是做分解查詢要具體情況具體分析。

如果資料庫的結構合理,索引設計得當,表連接的效率要高於分解查詢。比如,在有外鍵的時候,資料庫可以為外鍵建表並建立索引從而提升多個表連接查詢的效率。另外,多表連接查詢不需要把數據傳輸到應用程序中,直接在資料庫端執行,這在很大程度上提升了效率。

但是多表連接也有一些缺點。多表連接對表結構的依存度很高,只要表結構出現變更就會同時對資料庫檢索和應用處理兩個部分產生較大影響。另外,多表連接的兼容性不好,資料庫不同SQL文也多少有些差異。而且採用分散資料庫的時候,實現多表連接即麻煩又沒有什麼好處。因此,一些大型系統或者是支持多種類資料庫的系統一般不會使用多表連接,而傾向於採用分解查詢。

這個得看情況,一般數據不大的情況下多表連接查詢和多次單表查詢的效率差不多。如果數據量足夠大,那肯定是多次單表查詢的效率更高。在很多大的公司裡面,都會禁用多表連接查詢,原因就是一旦數據量足夠大的時候多表連接查詢效率會很慢,而且不利於分庫分表的查詢優化。那麼看一下下面這個例子。

兩種查詢方式的比較

我這里有一個資料庫,我們拿裡面的客戶表和地區表做兩種查詢的對比。用戶表數據是31萬條,地區表3511條。

1. 使用連表查詢成都市的客戶總數

2.使用多次單表查詢客戶總數

可以看到,查詢出來的結果都是一樣,但是第一種的連表查詢用了0.67秒中,而第二種多次單表查詢一共用時0.14秒。這個對比已經是很明顯了吧。

雖然這只是一個很簡單的例子,但是對比結果是非常明顯的。在實際應用中可能會更復雜、數據更多,如果還使用連表查詢時非常慢的,而且還消耗伺服器資源。

所以現在在很多大了公司明確要求禁止使用join查詢,比如阿里、騰訊就明確規定禁用三表以上的join查詢。

總結一下,單表查詢的優點

1. 多次單表查詢,讓緩存的效率更高。

許多應用程序可以方便地緩存單表查詢對應的結果對象。另外對於MySQL的查詢緩存來說,如果關聯中的某個表發生了變化,那麼就無法使用查詢緩存了,而拆分後,如果某個表很少改變,那麼基於該表的查詢就可以重復利用查詢緩存結果了。

2. 將查詢分解後,執行單個查詢可以減少鎖的競爭。

3. 在應用層做關聯,更容易對資料庫進行拆分,更容易做到高性能和可擴展。

4. 查詢本身效率也可能會有所提升。

5. 可以減少冗餘記錄的查詢。

6. 在應用中實現了哈希關聯,而不是使用MySQL的嵌套環關聯,某些場景哈希關聯的效率更高很多。

7. 單表查詢有利於後期數據量大了分庫分表,如果聯合查詢的話,一旦分庫,原來的sql都需要改動。

8. 很多大公司明確規定禁用join,因為數據量大的時候查詢確實很慢

所以在數據量不大的情況下,兩種方式的查詢都沒什麼明顯的差別,使用多表連接查詢更方便。但是在數據量足夠大幾十萬、幾百萬甚至上億的數據,或者在一些高並發、高性能的應用中,一般建議使用單表查詢。

如果覺得笨貓的回答對你有用,點個關注,非常感謝。

做java的,在orm框架下,分解查詢是最符合面向對象操作的,挺支持分解查詢的(拙見)

先說結論:不一定。

多表查詢效率低的時候,可以考慮拆解sql成多個小的sql,至於效率是否一定會提高,這個還不一定,具體問題具體問題。當多表查詢效率低的時候,拆解成單個小sql,這只是一個可能的思路,起不起作用,不一定。

sql是一個很復雜的東西,sql引擎會分析執行計劃,並可能按照他認為最優的執行計劃執行sql,但他認為的也不一定是正確的。不同的sql執行計劃不一樣,所以很難斷定sql拆解或者合並的效率。

說了這么多,那到底是多表聯合查詢還是拆解呢?有沒有一個原則? 有!如果你確定你的單個sql的執行效率比較快,當然可以寫多個單個sql。當然了,具備這個能力需要你對資料庫足夠了解,比如什麼時候走索引,什麼時候nested loop等等。如果你現在的多表聯合查詢比較慢,你需要找出來慢的原因,並分析拆解後的sql的執行計劃,看是否避免了多表聯合查詢的效率問題。


總之吧。這個問題,只能給你一個大體的思路,因為牽扯到很多基礎問題,我覺得最起碼sql執行計劃應該需要了解,一個sql可能的執行計劃有幾十中,復雜sql的執行計劃又是這幾十種的組合。哪種效率低,哪種效率高應該有個大體了解。


多表查詢可以很快,也可以很慢。主要看執行計劃。

單次肯定是多表連接查詢的效率高,但多次單表查詢的吞吐量高,而且容易優化,例如分庫分表,使用緩存減少DB訪問次數等等,所以在大數據量高並發場景通常使用多次單表查詢的方式。另外,不管是單表還是多表連接查詢,SQL的執行時間和數據量、並發量都有很大關系,和掃描的數據行數也很有關系。如果一條SQL,平時執行一次要2秒,10個並發時,系統可能一點問題都沒有,1000個並發時,資料庫可能就被拖死了。我們組之前碰到過好幾次這種問題,一張只有幾萬條數據的表,因為忘記加索引,平時執行只有幾百毫秒,高峰期直接飆到幾十秒,DB差點被拖垮。

單純從效率來講,join的表不太多時,join效率比較高。但是佔用的主要是資料庫伺服器的資源。資料庫資源又是個瓶頸,不易橫向擴展。所以在數據量大的時候,我們會採用單表查詢,把循環和匹配等大量工作移到應用伺服器上。應用伺服器容易擴展,對並發支持更好。

當數據量大到千萬級以上,就建議盡可能減少join,鼓勵使用單表查詢。查詢優化比較容易。這時候使用join的一個大型查詢就可能花很久,對其他查詢造成阻塞,導致服務不可用。

當考慮單表查詢後,就會衍生一系列的策略,比如冷熱數據分離,將熱數據和 歷史 數據分離,大幅降低數據量級以提高熱數據查詢性能,並可以使用內存緩存。這樣又促使你考慮引入微服務架構。

總結,數據量小,查詢並發少,那麼使用join的性能是可控的,開發成本低。當數量級上升到千萬級且不斷增加,盡早考慮向單表查詢切換,否則可能有性能下降會導致系統奔潰。而且性能下降不是線性的,會陡降。

⑹ SQL為什麼預估執行計劃與真實執行計劃會有差異

第一種,就是優化器的輸出結果,成為預估執行計劃,裡面的操作符或者步驟都是邏輯步驟,因為他們代表著執行計劃在優化器中的視圖,但是並不表現在實際執行中物理層面的發生。
另外一種計劃是表示查詢實際執行的輸出結果。這種類型叫做實際執行計劃,表示查詢在實際執行時發生的事情。
這兩個計劃顯示獨立的不同的結果集,但是可以看出有巨大的相同之處。大部分情況下,相同的開銷的相同的操作符會出現在兩種執行計劃中。但是當發生重編譯,SQLServer會刪除計劃緩存中的計劃並重建它,此時兩者就會有明顯的差異。這種情況通常發生於統計信息的更改,或存儲引擎在處理查詢時發生的其他事情。
預估執行計劃是存放在計劃緩存中的計劃,所以對於實際執行計劃,只能通過捕捉查詢運行的時候產生的執行計劃。預估計劃從不直接訪問數據,但是它對大型的、復雜的、可能運行很久的查詢分析相當有效。但是實際計劃是首選的,因為它能顯示很多運行過程中重要的統計信息如特定操作符實際訪問的行數。通常情況下,這種額外的信息使得實際計劃成為最常用的方式,但是預估計劃機器重要,特別是因為可以從計劃緩存中獲取。

⑺ 同一個SQL,在8個小時內為什麼會有不同的執行計劃有的快,有的慢

一般不是執行計劃不同,除非你有比如建立索引的等操作。
這個慢和快在這里,不是執行計劃決定,而是你的伺服器的情況不同,可能執行時cpu同時處理的所以慢內容很多,所以慢,也可能是內存導致的,也可能是io導致的,也就是說可能性很多,如果要分析那真的要一定時間。
當然,執行計劃也不一定完全一致,比如你會發現第二次查詢一般比第一次快,這是因為上次查詢的內容保存在內存中,只要還沒有被替換掉,那麼下次查詢就會快。這種在執行計劃上是看不出來的,但是確實也存在不同。

⑻ 什麼是sql執行計劃

執行計劃:就是一個sql語句執行數據的方式。
先採用何種方式操作 操作表,
採用那種順序操作表

⑼ Mysql學會查看sql的執行計劃

首先在Mysql的服務中有 連接器、查詢緩存(Mysql8 已經刪除)、分析器、優化器、執行器等,所有跨存儲引擎的功能都在這一層實現

而一條sql怎麼執行是由優化器決定的, 優化器是在表裡面有多個索引的時候,決定使用哪個索引;或者在一個語句有多表關聯(join)的時候,決定各個表的連接順序。

而執行計劃就是優化器優化後的sql的執行的詳細方案

Mysql中查看執行計劃的方式有兩種 : 1. 使用desc    2.使用 explain  使用它倆的效果是一樣的

接下來要通過執行計劃知道sql是怎麼執行的

執行計劃中有幾個重要的欄位, 分別是 

id,  table,  type,  possible_keys,  key,  key_len, Extra

id :  可以通過ID來查看在多表聯查中sql是先查詢哪張表的 id相同的從上往下依次執行,id不同的id大的先執行

table :   table當然就是查詢的表名

type :  查詢的類型   查詢類型分為  ALL,  index,  range,  ref , eq_ref, const(system),  null

        ALL: 指的全盤掃描,沒有走任何索引   查詢結果集大於25% 優化器可能會走全盤掃描   字元串查詢的時候一定要加"" 不然可能會全索引掃描(隱式轉換)   統計信息 失效 或者 過舊 也可能走全盤掃描  因為優化器會參考統計信息來制定執行計劃

        index: 全索引掃描  就是掃描整顆索引樹

           range: 索引范圍  查詢索引樹的一部分范圍   范圍索引中 >  <  <=  >=  like  的效率會比  or   in  的效率高, 使用like %再前面的不走索引

            ref:   輔助索引的等值查詢            

                    當查詢的數據量小,優化器也有可能會走索引的全盤掃描  這里我就不貼圖了;

            eq_ref : 多表連接查詢中,被連接的表的連接條件列是主鍵或者唯一鍵

            const(system): 主鍵 或者 唯一鍵 的等值查詢

               null: 沒有數據

            他們的性能是依次遞增的 全盤掃描性能最差,  const性能最高

possible_keys:  查詢過程中可能用到的索引

key: 真正使用到的索引

key_len:  走索引的長度

        這個是怎麼計算的呢?  

                key_len 的計算方法 :

                    int 類型最長存儲4個位元組長度的數字  有not null  是4位元組  沒有的話會花1位元組存儲是不是null

                    tinyint 最大存儲一個位元組    也會花1位元組來判斷是不是null

                    字元串類型 : 字元集 utf8mb4  1-4位元組

                    varchar超過255會預留2個位元組存儲長度 沒超預留1個位元組

                    key_len 永遠是你設置的長度的最大的  

        聯合索引可以通過key_len 來判斷走了幾個索引

        使用desc format=json select * from table 可以查看詳細情況

filtered:  索引掃描過濾掉數據的佔比

Extra: 額外的信息 

         Using filesort :MySQL 對數據在sql層進行了排序,而不是按照表內的索引進行排序讀 取。 效率比較低

         Using temporary :使用臨時表保存中間結果,也就是說 MySQL 在對查詢結果排序時使用了臨時表,常見於order by 或 group by。

         Using index :表示 SQL 操作中使用了覆蓋索引(Covering Index),避免了訪問表的數據行,效率高。

         Using index condition :表示 SQL 操作命中了索引,但不是所有的列數據都在索引樹上,還需要訪問實際的行記錄。

         Using where :表示 SQL 操作使用了 where 過濾條件。

         Select tables optimized away :基於索引優化 MIN/MAX 操作或者 MyISAM 存儲引擎優化 COUNT(*) 操作,不必等到執行階段再進行計算,查詢執行計劃生成的階段即可完成優化。

          Using join buffer (Block Nested Loop) :表示 SQL 操作使用了關聯查詢或者子查詢,且需要進行嵌套循環計算

 

⑽ mssql2008的資料庫,同一台伺服器,兩個表一模一樣,同一條SQL語句執行計劃不一樣,效果相差非常多。

復制過去的表沒有主資料庫中的索引信息,導致執行計劃相差非常多