sql語句百萬數據量優化方案

来源:http://www.cnblogs.com/cq-jiang/archive/2017/10/21/7681196.html
-Advertisement-
Play Games

一:理解sql執行順序 在sql中,第一個被執行的是from語句,每一個步驟都會產生一個虛擬表,該表供下一個步驟查詢時調用,比如語句:select top 10 column1,colum2,max(column3) from user where id>1 group by column1,col ...


一:理解sql執行順序

        在sql中,第一個被執行的是from語句,每一個步驟都會產生一個虛擬表,該表供下一個步驟查詢時調用,比如語句:select top 10 column1,colum2,max(column3) from user where id>1 group by column1,colum2 having count(column1)>1 order by colum2.

      sqlserver 2005 各個環節簡單介紹:

(8)SELECT (9)DISTINCT  (11)<Top Num> <select list>
(1)FROM [left_table]
(3)<join_type> JOIN <right_table>
(2)ON <join_condition>
(4)WHERE <where_condition>
(5)GROUP BY <group_by_list>
(6)WITH <CUBE | RollUP>
(7)HAVING <having_condition>
(10)ORDER BY <order_by_list>

   a)各個步驟簡介:

  1. FROM:對FROM子句中的多個表執行笛卡爾積(Cartesian product)(交叉聯接),生成虛擬表VT1
  2. ON:對VT1應用ON篩選器。只有那些使<join_condition>為真的行才被插入VT2。
  3. OUTER(JOIN):如 果指定了OUTER JOIN(相對於CROSS JOIN 或(INNER JOIN),保留表(preserved table:左外部聯接把左表標記為保留表,右外部聯接把右表標記為保留表,完全外部聯接把兩個表都標記為保留表)中未找到匹配的行將作為外部行添加到 VT2,生成VT3.如果FROM子句包含兩個以上的表,則對上一個聯接生成的結果表和下一個表重覆執行步驟1到步驟3,直到處理完所有的表為止。
  4. WHERE:對VT3應用WHERE篩選器。只有使<where_condition>為true的行才被插入VT4.
  5. GROUP BY:按GROUP BY子句中的列列表對VT4中的行分組,生成VT5.
  6. CUBE|ROLLUP:把超組(Suppergroups)插入VT5,生成VT6.
  7. HAVING:對VT6應用HAVING篩選器。只有使<having_condition>為true的組才會被插入VT7.
  8. SELECT:處理SELECT列表,產生VT8.
  9. DISTINCT:將重覆的行從VT8中移除,產生VT9.
  10. ORDER BY:將VT9中的行按ORDER BY 子句中的列列表排序,生成游標(VC10).
  11. TOP:從VC10的開始處選擇指定數量或比例的行,生成表VT11,並返回調用者.

 

  b)標準sql執行順序是:

  1:form 組裝來自不同表的數據,如 form user或者,form user as u join goodsOrder as r on u.id= r.userid

  2:where 過濾符合查詢條件的數據,如:id>1000

  3:group by 將查詢數據進行分組

  4:使用sum等聚合函數進行計算。

  5:使用having 進行篩選分組。

  6:執行select語種

  7:執行排序語句

  如:select count(gid),gname from shopping_goods where gcid=1 group by gname having count(gid)>1 order by count(gid) desc

  1:首頁查詢shopping_goods 表,得到表中的數據

  2:執行where,過濾出gcid=1的商品。

  3:對gname進行分組。

  4:使用聚合函數count(),計算出商品類型為1,不同商品名稱的數量.

  5:使用having,過濾出類型為1,商品統計數量大於1的商品

  6:執行select語句

  7:執行order by ,按照商品數量降序排列。

二:百萬數據量優化

  這裡只介紹查詢和修改的方法,如果是系統優化,需要從表結構,索引,表分區等方面處理。

  1:合理使用索引,在一個大數據量的表中,並不是索引越多越好,索引越多,寫操作越慢,建議在以下欄位上創建索引。

  ●在經常進行連接,但是沒有指定為外鍵的列上建立索引,而不經常連接的欄位則由優化器自動生成索引。

  ●在頻繁進行排序或分組(即進行group by或order by操作)的列上建立索引。

  ●在條件表達式中經常用到的不同值較多的列上建立檢索,在不同值少的列上不要建立索引。比如在雇員表的“性別”列上只有“男”與“女”兩個不同值,因此就無必要建立索引。如果建立索引不但不會提高查詢效率,反而會嚴重降低更新速度。

  ●如果待排序的列有多個,可以在這些列上建立複合索引(compound index)。

  ●使用系統工具。如Informix資料庫有一個tbcheck工具,可以在可疑的索引上進行檢查。在一些資料庫伺服器上,索引可能失效或者因為頻繁操作而使得讀取效率降低,如果一個使用索引的查詢不明不白地慢下來,可以試著用tbcheck工具檢查索引的完整性,必要時進行修複。另外,當資料庫表更新大量數據後,刪除並重建索引可以提高查詢速度。

  2:儘量少用(或者不用)sqlserver 自帶的函數

  a):如dateadd(month,-1,getdate()),請使用time>'2017-09-19 23:42:44.770 '代替dateadd.

  b):如datediff(day,'2017-10-20','2017-10-25'),select datepart(day,getdate());,如需計算兩個日期之前的差值,或者得到日期中的整數部分,建議查詢完畢後用java程式來計算,不要什麼都讓資料庫來做.

  c:) 如:substring(name,1,3) = ’abc’,建議修改為 name like 'abc%'

 

  3:儘量不要在 where 子句中對欄位進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,強烈建議where涉及的列,不要留空,創建表時賦予初始值

錯誤
select
id from table where name is not null
正確
create table table(name varchar(20) default '')

   4:應儘量避免在 where 子句中使用 != 或 <> 操作符,否則將引擎放棄使用索引而進行全表掃描。

   

錯誤
select id from table where id <> 100 

  5:應儘量避免在 where 子句中使用 or 來連接條件,如果一個欄位有索引,一個欄位沒有索引,將導致引擎放棄使用索引而進行全表掃描,建議使用unall 來代替or

  

select id from table where num=1 or Name = 'zhangsan'
建議修改為
select id from table where num=1 
unionall 
select id from table where  name = 'zhangsan'

  6:建議使用exists 來代替in,能用between 就不要使用in 如:age in (20,21,22)建議修改為:age between 20 and 22

  

select id from t where role in (select rid from role where rName = '經理','總監')
建議修改為
select id from t as a where exists (select rid from role  as b where a.role  = b.rid and rName = '經理')

  7:like 的用法

  除了 title  like '重慶%' ,其它使用方法(如:title like  '%王%' title like '%天')也將導致全表掃描

    8:where 中儘量不要出現表達式計算

  如:

select id from t where num/2 = 100

  應改為:

select id from t where num = 100*2

  9:Update 語句,如果只更改1、2個欄位,不要Update全部欄位,否則頻繁調用會引起明顯的性能消耗,同時帶來大量日誌。強烈建議修改時使用動態sql語句,類似hibernate中dynamic-update=true,不過hibernate需要將修改對像通過id查詢出來,才會動態修改,如果是普通sql,直接組裝就可以。

  10:對於多張大數據量(這裡幾百條就算大了)的表JOIN,要先分頁再JOIN,否則邏輯讀會很高,性能很差.

  11:不要寫一些沒有意義的查詢,如需要生成一個空表結構:

select col1,col2 into #t from t where 1=0

 

  12:儘量使用數字型欄位,若只含數值信息的欄位儘量不要設計為字元型,這會降低查詢和連接的性能,並會增加存儲開銷。這是因為引擎在處理查詢和連 接時會逐個比較字元串中每一個字元,而對於數字型而言只需要比較一次就夠了。

  13:儘可能的使用 varchar/nvarchar 代替 char/nchar ,因為首先變長欄位存儲空間小,可以節省存儲空間,其次對於查詢來說,在一個相對較小的欄位內搜索效率顯然要高些。

  14:不建議使用 select * from t ,用具體的欄位列表代替“*”,不要返回用不到的任何欄位。

  15:儘量避免使用游標,因為游標的效率較差,如果游標操作的數據超過1萬行,那麼就應該考慮改寫。

  16:在所有的存儲過程和觸發器的開始處設置 SET NOCOUNT ON ,在結束時設置 SET NOCOUNT OFF 。無需在執行存儲過程和觸發器的每個語句後向客戶端發送 DONE_IN_PROC 消息。

  17:儘量避免大事務操作,提高系統併發能力。並且不要事務嵌套,不要在事務中去調用其它系統的介面,不要在事務中耗時操作,不然死鎖並伴你左右

  18:儘量避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理。(筆者曾經處理過,從3000萬手機號碼庫中,模糊查詢出上萬個手機號碼,這種需求是客戶硬性要求,就要通過executorservice了,不要直接寫sql查)

  19:如果資料庫是mysql,一定要利用資料庫引擎,不同業務要使用不同的資料庫引擎。比如常用的innodb和myisam,innodb支持事務,支持外鍵,鎖是表級鎖,缺點是查詢速度慢,Myisam 的執行速度更快,性能更好,但不支持外鍵,不支持事務,鎖是行鎖級。比如日誌表,數據量大,強烈建議使用myisam引擎.

 

  以上有些來自網路,有些來自工作中的總結,後期還會完善,如有錯誤,請指出,謝謝。

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 實現目標 先來一張微信功能截圖看看要做什麼 其實就是有一個目的地,點擊目的地的時候彈出可選擇的應用進行導航。 大腦動一下,要實現這個功能應該大體分成兩步: 底部菜單這裡用PopupWindow來做。 實現 1、菜單顯示 PopupWindow支持傳入view進行彈出展示,所有我們直接寫一個菜單佈局, ...
  • 直奔主題 第一步:為AndroidStudio安裝Kotlin插件 線上安裝步驟:File—>Settings—>Plugins—>Install JetBrains plugin…出現以下界面,選中Kotlin 點擊右邊的Install(因為我的已經安裝了所以顯示的是Update升級) 然後就是漫 ...
  • 枚舉增強程式的可讀性,用法上還是需要註意的 1.C語言的寫法 enum XMPPReconnectFlags { kShouldReconnect = 1 << 0, // If set, disconnection was accidental, and autoReconnect may be ...
  • 首先,在正式使用Masonry之前,我們先來看看在xib中我們是如何使用AutoLayout 從圖中我們可以看出,只要設置相應得局限,控制好父視圖與子視圖之間的關係就應該很ok的拖出你需要的需求。這裡就不詳細講解具體拖拽的方法..... 然後,我們按著上圖的屬性來看看如何簡單得使用Masonry 首 ...
  • 最近公司有了一個新的需求,學生在購買課時的時候,需要讓家長或者朋友代付。這樣的話我首先想到的就是微信的H5支付(微信內置瀏覽器調用支付模塊)。當時想用這個支付的原因因為是前端代碼十分簡單。。 然而恰恰是因為自己選擇了這個方法,讓自己連續兩天陷入了困境。 下麵是正文跟代碼截圖 首先咱們先來看下H5的支 ...
  • 第一種方法:通過設置layer的屬性 最簡單的一種,但是很影響性能,一般在正常的開發中使用很少. ? 1 2 3 4 5 6 7 UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(100, 100, 100, ...
  • 引言 為了後面的例子做準備,本篇及接下來幾篇將介紹Android應用程式的原理及術語,這些也是作為一個Android的開發人員必須要瞭解,且深刻理解的東西。本篇的主題如下: 1、應用程式基礎 2、應用程式組件 2.1、活動(Activities) 2.2、服務(Services) 2.3、廣播接收者 ...
  • ——工欲善其事必先利其器 引言 本系列適合0基礎的人員,因為我就是從0開始的,此系列記錄我步入Android開發的一些經驗分享,望與君共勉!作為Android隊伍中的一個新人的我,如果有什麼不對的地方,還望不吝賜教。 在開始Android開發之旅啟動之前,首先要搭建環境,然後創建一個簡單的Hello ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...