最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python進(jìn)階技巧之利用break和哈希算法優(yōu)化數(shù)據(jù)庫(kù)批量操作

 更新時(shí)間:2026年01月12日 09:24:32   作者:小莊-Python辦公  
這篇文章主要為大家詳細(xì)介紹了Python如何利用break和哈希算法優(yōu)化數(shù)據(jù)庫(kù)批量操作,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下

第一章:為什么你的 Python 批量插入腳本總是又慢又占內(nèi)存?

在數(shù)據(jù)處理領(lǐng)域,Python 以其豐富的庫(kù)生態(tài)著稱(chēng),尤其是 psycopg2,作為連接 Python 與 PostgreSQL 數(shù)據(jù)庫(kù)的橋梁,被廣泛使用。然而,很多開(kāi)發(fā)者在編寫(xiě)批量數(shù)據(jù)遷移或同步腳本時(shí),往往陷入一個(gè)誤區(qū):一次性將所有數(shù)據(jù)讀入內(nèi)存,然后試圖一次性寫(xiě)入數(shù)據(jù)庫(kù)。

這種“全量加載”的模式在處理幾萬(wàn)行數(shù)據(jù)時(shí)或許還能應(yīng)付,但一旦面對(duì)百萬(wàn)級(jí)甚至千萬(wàn)級(jí)的數(shù)據(jù),內(nèi)存溢出(OOM)和極長(zhǎng)的 I/O 等待時(shí)間就會(huì)成為噩夢(mèng)。

本篇文章將結(jié)合三個(gè)核心概念——psycopg2 的游標(biāo)機(jī)制、哈希(Hash) 算法的預(yù)處理能力、以及 Python 的 break 流程控制——來(lái)探討如何編寫(xiě)高效、穩(wěn)健的數(shù)據(jù)庫(kù)批量處理腳本。我們將不再討論空洞的理論,而是直接深入實(shí)戰(zhàn),解決“慢”和“崩”的問(wèn)題。

第二章:利用break實(shí)現(xiàn)可控的流式處理

很多初學(xué)者在處理數(shù)據(jù)庫(kù)查詢結(jié)果時(shí),習(xí)慣使用 fetchall() 將所有結(jié)果加載到一個(gè)巨大的列表中。但在大數(shù)據(jù)場(chǎng)景下,這肯定是不行的。我們需要的是流式處理(Streaming),即一次只處理一小部分?jǐn)?shù)據(jù),處理完即丟棄,從而保持恒定的低內(nèi)存占用。

在 Python 的 psycopg2 中,我們可以結(jié)合 cursor 的迭代器特性與 break 語(yǔ)句來(lái)實(shí)現(xiàn)精細(xì)的流程控制。

2.1 擺脫fetchall()的陷阱

傳統(tǒng)的寫(xiě)法是這樣的:

# 危險(xiǎn)的寫(xiě)法!
cur.execute("SELECT * FROM huge_table")
rows = cur.fetchall()  # 如果表有1000萬(wàn)行,內(nèi)存直接爆炸
for row in rows:
    process(row)

2.2 結(jié)合break的分批處理邏輯

更高級(jí)的做法是利用 break 在滿足特定條件時(shí)中斷循環(huán),或者結(jié)合 enumerate 來(lái)實(shí)現(xiàn)“按批次中斷”。雖然 Python 的迭代器本身支持自動(dòng)的流式讀?。?for row in cursor:),但我們?cè)谔幚韽?fù)雜的業(yè)務(wù)邏輯時(shí),往往需要主動(dòng)介入。

實(shí)戰(zhàn)案例:模擬處理 100 萬(wàn)行數(shù)據(jù),每處理 1000 條就暫停并寫(xiě)入

在這里,break 的作用不僅僅是跳出循環(huán),它配合 while True 結(jié)構(gòu),可以實(shí)現(xiàn)類(lèi)似“生產(chǎn)者-消費(fèi)者”的斷點(diǎn)續(xù)傳機(jī)制。

import psycopg2

def batch_process(conn, batch_size=1000):
    cur = conn.cursor(name='fetch_large_data') # 創(chuàng)建服務(wù)器端游標(biāo)
    cur.execute("SELECT id, raw_data FROM big_table")
    
    results_batch = []
    
    while True:
        # 這里的 fetchmany 是關(guān)鍵,它每次只從服務(wù)器拉取 batch_size 行
        rows = cur.fetchmany(batch_size)
        
        if not rows:
            break # 沒(méi)有數(shù)據(jù)了,徹底跳出循環(huán)
            
        for row in rows:
            # 模擬復(fù)雜的業(yè)務(wù)邏輯處理
            processed_data = heavy_computation(row)
            results_batch.append(processed_data)
            
            # 這里的 break 是一種邏輯控制:
            # 假設(shè)我們?cè)谧鰯?shù)據(jù)清洗,如果發(fā)現(xiàn)某個(gè)標(biāo)志位異常,立即終止本次批次的后續(xù)處理
            if is_corrupted_data(processed_data):
                print("發(fā)現(xiàn)異常數(shù)據(jù),終止當(dāng)前批次處理")
                break # 跳出內(nèi)層 for 循環(huán),進(jìn)入下一輪 while 循環(huán)
        
        # 寫(xiě)入數(shù)據(jù)庫(kù)或外部存儲(chǔ)
        write_to_staging_table(results_batch)
        results_batch.clear() # 釋放內(nèi)存
        
    cur.close()

通過(guò)這種方式,break 賦予了我們對(duì)數(shù)據(jù)流的絕對(duì)控制權(quán)。我們不再被動(dòng)地等待整個(gè)數(shù)據(jù)集加載完成,而是像剝洋蔥一樣,一層一層地處理數(shù)據(jù),內(nèi)存占用始終維持在 batch_size * row_size 的極低水平。

第三章:引入哈希(Hash)算法:去重與快速校驗(yàn)

在批量處理中,除了速度,數(shù)據(jù)一致性也是重中之重。當(dāng)網(wǎng)絡(luò)中斷或程序崩潰時(shí),我們往往需要重新運(yùn)行腳本。如果腳本不具備冪等性(Idempotency),就會(huì)導(dǎo)致數(shù)據(jù)重復(fù)插入。

這時(shí)候,哈希(Hash) 算法就派上用場(chǎng)了。哈希可以將任意長(zhǎng)度的數(shù)據(jù)映射為固定長(zhǎng)度的字符串(指紋)。利用哈希,我們可以做兩件事:

  • 內(nèi)存級(jí)去重:在插入數(shù)據(jù)庫(kù)前,在 Python 內(nèi)存中利用 Set 快速過(guò)濾重復(fù)數(shù)據(jù)。
  • 增量同步:計(jì)算源數(shù)據(jù)的哈希值,與目標(biāo)數(shù)據(jù)庫(kù)中的哈希值對(duì)比,僅插入變更的數(shù)據(jù)。

3.1 實(shí)戰(zhàn)案例:基于哈希的增量數(shù)據(jù)同步

假設(shè)我們有一個(gè)日志表,每天需要從外部源同步新增數(shù)據(jù)。如果每次都全量對(duì)比,效率極低。我們可以預(yù)先計(jì)算每行數(shù)據(jù)的哈希值。

import hashlib

def generate_row_hash(row_data):
    """
    將行數(shù)據(jù)序列化并計(jì)算 MD5 哈希值
    """
    # 假設(shè) row_data 是一個(gè)字典或元組,先轉(zhuǎn)換為標(biāo)準(zhǔn)字符串
    data_str = str(sorted(row_data.items())) if isinstance(row_data, dict) else str(row_data)
    return hashlib.md5(data_str.encode('utf-8')).hexdigest()

def sync_data(conn, source_data_list):
    cur = conn.cursor()
    
    # 1. 獲取目標(biāo)數(shù)據(jù)庫(kù)中已存在的哈希集合
    cur.execute("SELECT row_hash FROM sync_log_table")
    existing_hashes = set([row[0] for row in cur.fetchall()])
    
    insert_list = []
    new_hashes = set()
    
    for item in source_data_list:
        # 2. 計(jì)算當(dāng)前數(shù)據(jù)的哈希
        current_hash = generate_row_hash(item)
        
        # 3. 哈希比對(duì):如果已存在,跳過(guò)
        if current_hash in existing_hashes or current_hash in new_hashes:
            continue
            
        new_hashes.add(current_hash)
        # 將數(shù)據(jù)和哈希值一起打包準(zhǔn)備插入
        insert_list.append((item['content'], current_hash))
        
        # 4. 利用 break 進(jìn)行內(nèi)存保護(hù)
        # 如果待插入列表過(guò)大,先寫(xiě)入一批,防止內(nèi)存暴漲
        if len(insert_list) >= 5000:
            execute_batch_insert(cur, insert_list)
            conn.commit()
            insert_list.clear()
            
    # 處理剩余數(shù)據(jù)
    if insert_list:
        execute_batch_insert(cur, insert_list)
        conn.commit()
        
    cur.close()

def execute_batch_insert(cursor, data):
    # 使用 psycopg2 的 execute_values 進(jìn)行高效批量插入
    from psycopg2.extras import execute_values
    sql = "INSERT INTO sync_log_table (content, row_hash) VALUES %s"
    execute_values(cursor, sql, data)

3.2 哈希優(yōu)化的思考

在這個(gè)章節(jié)中,哈希不僅僅是一個(gè)數(shù)學(xué)工具,它變成了數(shù)據(jù)處理的加速器。通過(guò)在 Python 層面進(jìn)行哈希比對(duì),我們避免了昂貴的數(shù)據(jù)庫(kù) I/O 操作。只有真正需要插入的數(shù)據(jù)才會(huì)觸達(dá)數(shù)據(jù)庫(kù),這使得腳本在網(wǎng)絡(luò)波動(dòng)或斷網(wǎng)重連后,具備了自動(dòng)“續(xù)傳”的能力。

值得注意的是,雖然計(jì)算哈希需要消耗一定的 CPU,但相比于數(shù)據(jù)庫(kù)的 I/O 延遲和磁盤(pán)尋道時(shí)間,這點(diǎn) CPU 消耗是完全可以接受的“保護(hù)費(fèi)”。

第四章:終極整合——構(gòu)建一個(gè)健壯的 ETL 腳本框架

現(xiàn)在,我們將 psycopg2 的連接管理、哈希 的去重校驗(yàn)、以及 break 的流程控制整合在一起,構(gòu)建一個(gè)生產(chǎn)級(jí)別的 ETL(Extract, Transform, Load)腳本骨架。

4.1 完整的錯(cuò)誤處理與重試機(jī)制

在實(shí)際生產(chǎn)中,僅僅有 break 是不夠的。我們需要處理數(shù)據(jù)庫(kù)連接斷開(kāi)、死鎖等異常。結(jié)合 Python 的 try-except 和循環(huán)控制,我們可以構(gòu)建一個(gè)極其穩(wěn)健的系統(tǒng)。

def robust_etl_pipeline():
    """
    整合了哈希校驗(yàn)、流式處理(break)和異常重試的完整流程
    """
    conn = get_db_connection()
    # 開(kāi)啟自動(dòng)提交,或者在循環(huán)內(nèi)手動(dòng) commit
    # conn.autocommit = False 
    
    try:
        # 源數(shù)據(jù)游標(biāo)
        source_cur = conn.cursor(name='source_cursor')
        source_cur.execute("SELECT * FROM source_table")
        
        # 目標(biāo)表準(zhǔn)備
        target_cur = conn.cursor()
        
        batch_buffer = []
        processed_count = 0
        
        while True:
            # 1. 流式讀取
            rows = source_cur.fetchmany(1000)
            if not rows:
                print("所有數(shù)據(jù)處理完畢。")
                break
            
            for row in rows:
                # 2. 哈希計(jì)算與校驗(yàn)
                row_hash = hashlib.md5(str(row).encode()).hexdigest()
                
                # 簡(jiǎn)單的去重檢查(實(shí)際中可查表或維護(hù)內(nèi)存集合)
                if is_duplicate(target_cur, row_hash):
                    continue
                
                # 3. 數(shù)據(jù)轉(zhuǎn)換
                transformed = transform(row)
                batch_buffer.append((transformed, row_hash))
                
            # 4. 批量寫(xiě)入
            if batch_buffer:
                try:
                    # 使用 execute_values 高效寫(xiě)入
                    from psycopg2.extras import execute_values
                    execute_values(
                        target_cur,
                        "INSERT INTO target_table (data, hash) VALUES %s ON CONFLICT DO NOTHING",
                        batch_buffer
                    )
                    conn.commit()
                    processed_count += len(batch_buffer)
                    print(f"已處理 {processed_count} 條數(shù)據(jù)...")
                    batch_buffer.clear()
                except Exception as e:
                    print(f"寫(xiě)入失敗: {e}")
                    conn.rollback()
                    # 這里可以加入重試邏輯
                    # time.sleep(5) 并嘗試重連
                    break # 寫(xiě)入失敗,停止處理,防止數(shù)據(jù)污染

    except Exception as e:
        print(f"發(fā)生嚴(yán)重錯(cuò)誤: {e}")
    finally:
        if conn:
            conn.close()

def is_duplicate(cursor, hash_val):
    cursor.execute("SELECT 1 FROM target_table WHERE hash = %s", (hash_val,))
    return cursor.fetchone() is not None

def transform(row):
    # 模擬數(shù)據(jù)轉(zhuǎn)換
    return row[1].upper() 

4.2 關(guān)鍵點(diǎn)總結(jié)

  • break 的雙重身份:它既是循環(huán)的終結(jié)者,也是異常流程的剎車(chē)片。在上述代碼中,一旦寫(xiě)入失敗,break 立即介入,防止錯(cuò)誤數(shù)據(jù)不斷累積。
  • 哈希的前置校驗(yàn):將沖突檢測(cè)從數(shù)據(jù)庫(kù)層(慢)前移到應(yīng)用層(快),利用內(nèi)存 Set 或預(yù)查詢,極大提升了同步效率。
  • psycopg2 的游標(biāo)策略:使用命名游標(biāo)(name='...')或 fetchmany 是處理大數(shù)據(jù)集的黃金法則。

第五章:總結(jié)與互動(dòng)

在 Python 與 PostgreSQL 的配合中,我們不應(yīng)僅僅滿足于“功能實(shí)現(xiàn)”,更要追求“工程效率”。

  • break 教會(huì)了我們克制:在數(shù)據(jù)洪流面前,懂得何時(shí)停下來(lái),處理好手頭的批次,比盲目吞吐更重要。
  • 哈希(Hash) 教會(huì)了我們智慧:通過(guò)提取數(shù)據(jù)的特征指紋,我們用極小的空間代價(jià)換取了數(shù)據(jù)完整性的保障。
  • psycopg2 則提供了基礎(chǔ):它是連接計(jì)算與存儲(chǔ)的可靠管道。

通過(guò)這三個(gè)維度的組合,我們不再是簡(jiǎn)單的“搬運(yùn)工”,而是成為了數(shù)據(jù)流動(dòng)的“指揮官”。

到此這篇關(guān)于Python進(jìn)階技巧之利用break和哈希算法優(yōu)化數(shù)據(jù)庫(kù)批量操作的文章就介紹到這了,更多相關(guān)Python數(shù)據(jù)庫(kù)批量操作優(yōu)化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • python列表的切片賦值實(shí)現(xiàn)

    python列表的切片賦值實(shí)現(xiàn)

    Python列表切片賦值是一種將一個(gè)列表的特定部分替換為新的元素的操作,本文主要介紹了python列表的切片賦值實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-03-03
  • Python標(biāo)準(zhǔn)庫(kù)time使用方式詳解

    Python標(biāo)準(zhǔn)庫(kù)time使用方式詳解

    這篇文章主要介紹了Python標(biāo)準(zhǔn)庫(kù)time使用方式詳解,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下
    2022-07-07
  • Win10下安裝CUDA11.0+CUDNN8.0+tensorflow-gpu2.4.1+pytorch1.7.0+paddlepaddle-gpu2.0.0

    Win10下安裝CUDA11.0+CUDNN8.0+tensorflow-gpu2.4.1+pytorch1.7.0+p

    這篇文章主要介紹了Win10下安裝CUDA11.0+CUDNN8.0+tensorflow-gpu2.4.1+pytorch1.7.0+paddlepaddle-gpu2.0.0,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • python排序算法的簡(jiǎn)單實(shí)現(xiàn)方法

    python排序算法的簡(jiǎn)單實(shí)現(xiàn)方法

    這篇文章主要給大家介紹了關(guān)于python排序算法的簡(jiǎn)單實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • Python3 pywin32模塊安裝的詳細(xì)步驟

    Python3 pywin32模塊安裝的詳細(xì)步驟

    這篇文章主要介紹了Python3 pywin32模塊安裝的詳細(xì)步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • PyTorch中 tensor.detach() 和 tensor.data 的區(qū)別解析

    PyTorch中 tensor.detach() 和 tensor.data 的

    這篇文章主要介紹了PyTorch中 tensor.detach() 和 tensor.data 的區(qū)別解析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-04-04
  • VSCode設(shè)置Python語(yǔ)言自動(dòng)格式化的詳細(xì)方案

    VSCode設(shè)置Python語(yǔ)言自動(dòng)格式化的詳細(xì)方案

    VSCode Python自動(dòng)格式化是指使用VSCode編輯器中的Python插件,可以自動(dòng)對(duì)Python代碼進(jìn)行格式化,使其符合PEP 8規(guī)范,這篇文章主要給大家介紹了關(guān)于VSCode設(shè)置Python語(yǔ)言自動(dòng)格式化的詳細(xì)方案,需要的朋友可以參考下
    2023-07-07
  • Python爬蟲(chóng)selenium驗(yàn)證之中文識(shí)別點(diǎn)選+圖片驗(yàn)證碼案例(最新推薦)

    Python爬蟲(chóng)selenium驗(yàn)證之中文識(shí)別點(diǎn)選+圖片驗(yàn)證碼案例(最新推薦)

    本文介紹了如何使用Python和Selenium結(jié)合ddddocr庫(kù)實(shí)現(xiàn)圖片驗(yàn)證碼的識(shí)別和點(diǎn)擊功能,感興趣的朋友一起看看吧
    2025-02-02
  • 使用Python對(duì)Excel表內(nèi)容進(jìn)行中文提取的示例代碼

    使用Python對(duì)Excel表內(nèi)容進(jìn)行中文提取的示例代碼

    本項(xiàng)目是基于Tkinter的圖形界面應(yīng)用程序,用于從Excel文件中提取符合特定正則表達(dá)式模式(默認(rèn)提取中文)的文本內(nèi)容,并將結(jié)果輸出到指定列或新文件中,感興趣的小伙伴跟著小編一起來(lái)看看吧
    2025-11-11
  • postman模擬訪問(wèn)具有Session的post請(qǐng)求方法

    postman模擬訪問(wèn)具有Session的post請(qǐng)求方法

    今天小編就為大家分享一篇postman模擬訪問(wèn)具有Session的post請(qǐng)求方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-07-07

最新評(píng)論

车险| 汤阴县| 崇义县| 长宁县| 舞钢市| 高青县| 锡林郭勒盟| 玉门市| 四会市| 盐亭县| 新津县| 喜德县| 抚宁县| 河间市| 大竹县| 长葛市| 吉林省| 汶川县| 章丘市| 淳化县| 夹江县| 随州市| 行唐县| 安徽省| 梅河口市| 甘泉县| 克山县| 左贡县| 兴仁县| 牡丹江市| 合水县| 广宗县| 余庆县| 富顺县| 余庆县| 北川| 当阳市| 松原市| 丽江市| 依兰县| 江都市|