真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

如何修復(fù)使用PythonORM工具SQLAlchemy時(shí)的陷阱

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)碛嘘P(guān)如何修復(fù)使用Python ORM工具SQLAlchemy時(shí)的陷阱,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

創(chuàng)新互聯(lián)建站專注于企業(yè)營銷型網(wǎng)站建設(shè)、網(wǎng)站重做改版、靈武網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、HTML5、商城開發(fā)、集團(tuán)公司官網(wǎng)建設(shè)、成都外貿(mào)網(wǎng)站制作、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為靈武等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。

在使用 SQLAlchemy 時(shí),那些看似很小的選擇可能對這種對象關(guān)系映射工具包的性能產(chǎn)生重要影響。

對象關(guān)系映射Object-relational mapping(ORM)使應(yīng)用程序開發(fā)人員的工作更輕松,在很大程度是因?yàn)樗试S你使用你可能知道的語言(例如 Python)與數(shù)據(jù)庫交互,而不是使用原始 SQL 語句查詢。SQLAlchemy  是一個(gè) Python ORM 工具包,它提供使用 Python 訪問 SQL 數(shù)據(jù)庫的功能。它是一個(gè)成熟的 ORM  工具,增加了模型關(guān)系、強(qiáng)大的查詢構(gòu)造范式、簡單的序列化等優(yōu)點(diǎn)。然而,它的易用性使得人們很容易忘記其背后發(fā)生了什么。使用 SQLAlchemy  時(shí)做出的看似很小的選擇可能產(chǎn)生非常大的性能影響。

解釋開發(fā)人員在使用 SQLAlchemy 時(shí)遇到的一些最重要的性能問題,以及如何解決這些問題。

只需要計(jì)數(shù)但檢索整個(gè)結(jié)果集

有時(shí)開發(fā)人員只需要一個(gè)結(jié)果計(jì)數(shù),但是沒有使用數(shù)據(jù)庫計(jì)數(shù)功能,而是獲取了所有結(jié)果,然后使用 Python 中的 len 完成計(jì)數(shù)。

count = len(User.query.filter_by(acct_active=True).all())

相反,使用 SQLAlchemy 的 count 方法將在服務(wù)器端執(zhí)行計(jì)數(shù),從而減少發(fā)送到客戶端的數(shù)據(jù)。在前面的例子中調(diào)用 all() 也會(huì)導(dǎo)致模型對象的實(shí)例化,如果有很多數(shù)據(jù),那么時(shí)間代價(jià)可能會(huì)非常昂貴。

除非還需要做其他的事情,否則只需使用 count 方法:

count = User.query.filter_by(acct_active=True).count()

只需要幾列時(shí)檢索整個(gè)模型

在許多情況下,發(fā)出查詢時(shí)只需要幾列數(shù)據(jù)。SQLAlchemy 可以只獲取你想要的列,而不是返回整個(gè)模型實(shí)例。這不僅減少了發(fā)送的數(shù)據(jù)量,還避免了實(shí)例化整個(gè)對象。使用列數(shù)據(jù)的元組而不是模型可以快得多。

result = User.query.all()for user in result:    print(user.name, user.email)

反之,使用 with_entities 方法只選擇所需要的內(nèi)容:

result = User.query.with_entities(User.name, User.email).all()for (username, email) in result:    print(username, email)

每次循環(huán)都更新一個(gè)對象

避免使用循環(huán)來單獨(dú)更新集合。雖然數(shù)據(jù)庫可以非常快地執(zhí)行單個(gè)更新,但應(yīng)用程序和數(shù)據(jù)庫服務(wù)器之間的往返時(shí)間將快速累加。通常,在合理的情況下爭取更少的查詢。

for user in users_to_update:  user.acct_active = True  db.session.add(user)

改用批量更新方法:

query = User.query.filter(user.id.in_([user.id for user in users_to_update]))query.update({"acct_active": True}, synchronize_session=False)

觸發(fā)級(jí)聯(lián)刪除

ORM 允許在模型關(guān)系上進(jìn)行簡單的配置,但是有一些微妙的行為可能會(huì)令人吃驚。大多數(shù)數(shù)據(jù)庫通過外鍵和各種級(jí)聯(lián)選項(xiàng)維護(hù)關(guān)系完整性。SQLAlchemy 允許你使用外鍵和級(jí)聯(lián)選項(xiàng)定義模型,但是 ORM 具有自己的級(jí)聯(lián)邏輯,可以取代數(shù)據(jù)庫。

考慮以下模型:

class Artist(Base):    __tablename__ = "artist"     id = Column(Integer, primary_key=True)    songs = relationship("Song", cascade="all, delete")  class Song(Base):    __tablename__ = "song"     id = Column(Integer, primary_key=True)    artist_id = Column(Integer, ForeignKey("artist.id", ondelete="CASCADE"))

刪除歌手將導(dǎo)致 ORM 在 song 表上發(fā)出 delete 查詢,從而防止由于外鍵導(dǎo)致的刪除操作。這種行為可能會(huì)成為復(fù)雜關(guān)系和大量記錄的瓶頸。

請包含 passive_deletes 選項(xiàng),以確保讓數(shù)據(jù)庫來管理關(guān)系。但是,請確保你的數(shù)據(jù)庫具有此功能。例如,SQLite 默認(rèn)情況下不管理外鍵。

songs = relationship("Song", cascade  all, delete", passive_deletes=True)

當(dāng)要使用貪婪加載時(shí),應(yīng)使用延遲加載

延遲加載是 SQLAlchemy 處理關(guān)系的默認(rèn)方法。從上一個(gè)例子構(gòu)建來看,加載一個(gè)歌手時(shí)不會(huì)同時(shí)加載他或她的歌曲。這通常是一個(gè)好主意,但是如果總是需要加載某些關(guān)系,單獨(dú)的查詢可能會(huì)造成浪費(fèi)。

如果允許以延遲方式加載關(guān)系,像 Marshmallow 這樣流行的序列化框架可以觸發(fā)級(jí)聯(lián)查詢。

有幾種方法可以控制此行為。最簡單的方法是通過 relationship 函數(shù)本身。

songs = relationship("Song", lazy="joined", cascade="all, delete")

這將導(dǎo)致一個(gè)左連接被添加到任何歌手的查詢中,因此,songs 集合將立即可用。盡管有更多數(shù)據(jù)返回給客戶端,但往返次數(shù)可能會(huì)少得多。

SQLAlchemy 為無法采用這種綜合方法的情況提供了更細(xì)粒度的控制,可以使用 joinedload() 函數(shù)在每個(gè)查詢的基礎(chǔ)上切換連接的加載。

from sqlalchemy.orm import joinedload artists = Artist.query.options(joinedload(Artist.songs))print(artists.songs) # Does not incur a roundtrip to load

使用 ORM 進(jìn)行批量記錄導(dǎo)入

導(dǎo)入成千上萬條記錄時(shí),構(gòu)建完整模型實(shí)例的開銷會(huì)成為主要瓶頸。想象一下,從一個(gè)文件中加載數(shù)千首歌曲記錄,其中每首歌曲都先被轉(zhuǎn)換為字典。

for song in songs:    db.session.add(Song(`song))

相反,繞過 ORM,只使用核心的 SQLAlchemy 參數(shù)綁定功能。

batch = []insert_stmt = Song.__table__.insert()for song in songs:    if len(batch) > 1000:       db.session.execute(insert_stmt, batch)       batch.clear()    batch.append(song)if batch:    db.session.execute(insert_stmt, batch)

請記住,此方法會(huì)自然而然地跳過你可能依賴的任何客戶端 ORM 邏輯,例如基于 Python 的列默認(rèn)值。盡管此方法比將對象加載為完整的模型實(shí)例要快,但是你的數(shù)據(jù)庫可能具有更快的批量加載方法。例如,PostgreSQL 的 COPY 命令為加載大量記錄提供了最佳性能。

過早調(diào)用提交或刷新

在很多情況下,你需要將子記錄與其父記錄相關(guān)聯(lián),反之亦然。一種顯然的方法是刷新會(huì)話,以便為有問題的記錄分配一個(gè) ID。

artist = Artist(name="Bob Dylan")song = Song(title="Mr. Tambourine Man") db.session.add(artist)db.session.flush() song.artist_id = artist.id

對于每個(gè)請求,多次提交或刷新通常是不必要的,也是不可取的。數(shù)據(jù)庫刷新涉及強(qiáng)制在數(shù)據(jù)庫服務(wù)器上進(jìn)行磁盤寫入,在大多數(shù)情況下,客戶端將阻塞,直到服務(wù)器確認(rèn)已寫入數(shù)據(jù)為止。

SQLAlchemy 可以在幕后跟蹤關(guān)系和管理相關(guān)鍵。

artist = Artist(name="Bob Dylan")song = Song(title="Mr. Tambourine Man") artist.songs.append(song)

總結(jié)

我希望這一系列常見的陷阱可以幫助你避免這些問題,并使你的應(yīng)用平穩(wěn)運(yùn)行。通常,在診斷性能問題時(shí),測量是關(guān)鍵。大多數(shù)數(shù)據(jù)庫都提供性能診斷功能,可以幫助你定位問題,例如 PostgreSQL 的 pg_stat_statements 模塊。

上述就是小編為大家分享的如何修復(fù)使用Python ORM工具SQLAlchemy時(shí)的陷阱了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。


新聞標(biāo)題:如何修復(fù)使用PythonORM工具SQLAlchemy時(shí)的陷阱
URL鏈接:http://weahome.cn/article/iedchc.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部