<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    大大毛 的筆記

      DDM's Note

    哪怕沒有辦法一定有說法,
    就算沒有鴿子一定有烏鴉,
    固執無罪 夢想有價,
    讓他們驚訝.

    posts - 14, comments - 23, trackbacks - 0, articles - 58
       :: 首頁 ::  :: 聯系 ::  :: 管理

    大資料量SQL性能優化之轉換思路

    Posted on 2008-11-11 18:55 大大毛 閱讀(517) 評論(0)  編輯  收藏 所屬分類: SQL

    問題?

    ??????這一次有同事在做一個小CASE時遇到問題無法解決. 整個的需求比較簡單, 是需要從資料庫中撈資料出來進行列印, 需求如下:
    ??????1. 從tbMain中找符合條件的客戶.限定條件:只有一筆資料的客戶
    ??????2. 查詢tbForeclose, 剔除掉某些客戶.剔除條件:姓名存在於tbForeclose中的客戶即要從名單中剔除
    ??????3. 從tbDetail中撈客戶的明細資料出來進行列印.關聯條件:依tbMain中客戶ID直接帶出即可

    -- 主檔(同一客戶會有多筆資料)
    Create ? Table ?tbMain?(
    ????aID?
    int ? identity ( 1 , 1 ),
    ????pID?
    varchar ( 10 )? not ? null ,???? -- 客戶ID
    ????pName? nvarchar ( 20 )? not ? null ,???? -- 客戶姓名
    ????pDoing? varchar ( 20 )? not ? null
    );
    -- 剔除客戶檔(僅存放客戶姓名)
    Create ? Table ?tbForeclose?(
    ????pName?
    nvarchar ( 20 )? not ? null ???? -- 剔除客戶姓名
    );
    -- 客戶資料明細檔
    Create ? Table ?tbDetail?(
    ????pID?
    varchar ( 10 )? primary ? key ,???? -- 客戶ID(KEY)
    ????pSex? char ( 1 )? not ? null ???????? -- 客戶其他詳細資料
    );

    ?

    示例數據

    嘗試及解決
    ??????就此需求表面來看, 實現起來很是簡單, 只要一條SQL就好:

    Select
    ????????
    *
    ????
    From
    ????????tbDetail
    ????
    Inner ? Join ?(
    ????????
    Select
    ????????????????pID,pName
    ????????????
    From
    ????????????????tbMain
    ????????????
    Where
    ????????????????
    Not ? Exists ?( Select ? 1 ? From ?tbForeclose? Where ?tbForeclose.pName = tbMain.pName)
    ????????????
    Group ? By
    ????????????????pID,pName
    ????????????
    Having
    ????????????????
    Count ( * ) = 1
    ????)?tbMain1?
    On ?tbMain1.pID = tbDetail.pID

    ??????但此需求在開發時卻有遇到一些限制條件, 不能這樣去實現.
    ??????限制條件:
    ?????????1. tbMain,tbForeclose,tbDetail三表分別存在於不同的DB, 因DB所屬系統各不相同, 線上環境則會有可能布署在不同DBServer上.
    ?????????2. tbMain記錄筆數極大,索引效率低下.
    ?????????3. 三張TABLE是屬於其他的系統, 本次需求不允許進行UPDATE的操作.
    ??????因此, 需要對應解決.

    ??????對於限制條件1, 資料處理必須依3個步驟進行(見圖上A,B,C), 如圖1:
    ????????????????????????o_1.jpg

    ??????對於限制條件2, 主要卡在步驟A的超時上(其後都僅處理到少量資料), 實測時在本機的查詢分析器RUN步驟A的SQL就要10分鍾,符合的資料筆數為百萬左右.除非是將ADO連線設為不超時, 否則一定會查詢失敗.

    ??????我首先的想法就是想要提高查詢效率.?
    ?????????. 經檢查tbMain發現pID列上有索引而pName上卻無, 所以將步驟A進行分解, 僅查詢符合的pID, 實測步驟A1可以在10分鍾以內完成, 見圖2.
    ???????????????????????????o_2.jpg
    ?????????. 嘗試減少步驟A1的處理筆數, 比如先依pID的前兩碼進行分組, 再進行多次查詢, 實測資料量最大的一組pID約在2-3分鍾, 單次資料量減少到十萬.
    ??????通過測試的結果可以看到該問題僅通過改善/分解查詢已經不能實現解決.?

    ??????那麼是否能夠將步驟A的筆數減少到一筆呢?
    ?????????. 因三檔都不允許進行UPDATE的操作, 在處理完TOP 1的一筆後因無法對處理過的pID進行標識, 無法獲取下一筆的資料.

    ??????既然多種方法都不可行, 那麼就只有完全改變處理的流程, 通過多添加一張表(專為此開發而新增的TABLE)並將消耗最大的步驟A交由DB內部來完成, 最終解決方法步驟如下:
    ??????1. 先手工新增臨時TABLE
    ??????
    --新增臨時檔
    Create?Table?tbTemp?(
    ????aID?
    int?identity(1,1),
    ????pID?
    varchar(10)
    );

    ??????2. 如果是需要多次RUN的話, 則要先Truncate Table tbTemp, 然後通過Insert Into tbTemp Select....在DB內部完成資料的篩選, 由於在客戶端不需要撈一筆資料, 所以耗時非常的短, 達到秒級.
    ??????3. 由於新增檔案是有KEY值(Identity), 所以只要拿到批次添加的最大/最小ID值即可通過循環來逐筆處理了.
    ??????最終解決方案如圖3
    ??????????????????????????????
    ???????????????????????????o_3.jpg

    i am ddm

    主站蜘蛛池模板: 久久精品亚洲综合| 亚洲真人无码永久在线| 91精品国产亚洲爽啪在线影院 | 亚洲综合另类小说色区色噜噜| 亚洲最大天堂无码精品区| 野花高清在线观看免费3中文| 亚洲国产成人精品电影| 91久久精品国产免费一区| 亚洲系列中文字幕| 日本成年免费网站| 亚洲五月综合网色九月色| 成人黄页网站免费观看大全| 中文字幕亚洲综合久久综合| 大陆一级毛片免费视频观看i| 亚洲AV无码一区二区大桥未久| 免费永久在线观看黄网站| 成人国产网站v片免费观看| 中文字幕久久亚洲一区| 在线涩涩免费观看国产精品| 亚洲另类激情综合偷自拍| 成人免费在线看片| 亚洲成a∨人片在无码2023| 又爽又黄无遮挡高清免费视频 | 久久久久国产精品免费免费不卡 | 亚洲人成在线播放网站岛国| 久久国产免费福利永久| 亚洲精品一卡2卡3卡四卡乱码| 亚洲国产小视频精品久久久三级| 丁香花在线观看免费观看图片| 久久久国产精品亚洲一区| 我想看一级毛片免费的| 又大又硬又粗又黄的视频免费看| 久久夜色精品国产亚洲| 国产在线观看片a免费观看| 美女被艹免费视频| 久久夜色精品国产嚕嚕亚洲av| 国产成人午夜精品免费视频 | 中文字幕乱码免费看电影| 亚洲精品午夜视频| 深夜国产福利99亚洲视频| 久久久久久精品免费看SSS|