日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[NewLife.XCode]高级查询(化繁为简、分页提升性能)

發(fā)布時間:2023/12/4 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [NewLife.XCode]高级查询(化繁为简、分页提升性能) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

NewLife.XCode是一個有10多年歷史的開源數(shù)據(jù)中間件,支持nfx/netcore,由新生命團隊(2002~2019)開發(fā)完成并維護至今,以下簡稱XCode。

整個系列教程會大量結合示例代碼和運行日志來進行深入分析,蘊含多年開發(fā)經(jīng)驗于其中,代表作有百億級大數(shù)據(jù)實時計算項目。

開源地址:https://github.com/NewLifeX/X (求star, 754+)

?

回到目錄

擴展查詢

前文《[NewLife.XCode]實體類詳解》中有講到擴展查詢,XCode生成實體類代碼時,在模型類有一個region叫“擴展查詢”,一般是FindByAbc/FindAllByAbc的形式。

擴展查詢以數(shù)據(jù)表索引為依據(jù)來生成:

  • 唯一索引(含主鍵)生成FindByAbc方法(如FindByName),返回單個對象;

  • 非唯一索引生成FindAllByAbc方法(如FindAllByClassID),返回對象列表(非null);

如上圖,可知Entity實體基類內(nèi)部,查詢方法分為單對象查詢的Find和對象列表的查詢FindAll。

實際上,Find最終調(diào)用FindAll方法查一行。

?

Find/FindAll有多個重載,最主要的地方都是構造where查詢條件。

下劃線_是每個實體類都有的內(nèi)嵌類,它包含了每一個字段的Field引用,借助運算符重載,可以很方便的構造查詢條件,例如上面的_.Name == name最終會生成 where Name='Stone'

因為是內(nèi)嵌類,在實體類內(nèi)部使用的時候非常方便。但要是想要實體類外部使用,就麻煩很多了,需要帶上實體類類名。

?

原則:XCode是充血模型,不管多么簡單的查詢,建議都封裝Find/FindAll/Search等方法供外部使用。

?

回到目錄

高級表達式查詢

僅靠一兩個字段的簡單查詢,肯定無法滿足各種業(yè)務要求,我們需要更強大的查詢支持,特別是根據(jù)不同條件拼接不同語句。

上面是兩個非常典型的業(yè)務查詢。

這里請出了條件表達式WhereExpression,實際上它只有兩個功能,&表示And,|表示Or,根據(jù)表達式級別支持括號運算。

exp&=xxx 是最常用的寫法,右邊一般是各種Field表達式。

上面第一個例子,生成的查詢語句可能是 select * from Student where classid=?classid and name like '%?key%'

為什么說“可能”?因為classid為0,或者key為空時,并不會參與拼接查詢語句。

?

第二個例子稍微復雜一些,首先對key進行精確查詢,找到了就返回,若是沒找到,則開啟模糊查詢。

這里遇到了等于、包含、區(qū)間等判斷操作,后面會詳解所有支持的操作。

?

如非必要,建議保留select * 的查詢方式,而不是指定列。

碼農(nóng)法則:數(shù)據(jù)庫壓力小于100qps時不要考慮指明select列來優(yōu)化,大多數(shù)系統(tǒng)活不到需要優(yōu)化的明天!

?

回到目錄

高級分頁?

兩個例子都出現(xiàn)了一個PageParameter參數(shù)page,這是分頁參數(shù),包含分頁查詢以及排序所需要的數(shù)據(jù)。

PageIndex和PageSize指定頁序號和每頁大小,這是內(nèi)部建立分頁查詢的核心依據(jù);

Sort 指定排序字段,Desc 指定是否降序(默認升序);

RetrieveTotalCount 指定是否或者總記錄數(shù),若為true,則在查詢記錄集之前,先查詢滿足條件的總行數(shù)TotalCount,用于分頁PageCount。此時等于執(zhí)行兩次數(shù)據(jù)庫查詢;

RetrieveState 指定是否獲取統(tǒng)計 State,若為true,則在查詢記錄集之后,執(zhí)行聚合查詢,對數(shù)字型字段使用Sum聚合。此時最多可能執(zhí)行3次數(shù)據(jù)庫查詢;

在執(zhí)行FindAll查詢時,若有傳入 PageParameter 且 RetrieveTotalCount 為true,則先查詢滿足條件的記錄數(shù),大于0時才查某一頁數(shù)據(jù)。

如果 Meta.Count 評估認為本表總行數(shù)超過100萬,且FindAll查詢沒帶有條件,則page.TotalCount直接取Meta.Count(少量偏差),以避免極大的FindCount耗時。

100萬行以上數(shù)據(jù)表,如若不帶條件或者條件沒有命中索引,select count?將會極其的慢,在1000萬以上甚至查不出來,這是XCode能對100億表進行分頁查詢的關鍵所在

?

Meta.Count 的初始值來自于數(shù)據(jù)庫元數(shù)據(jù)索引表,里面有該表主鍵的總行數(shù),取得該值后如果小于100萬再異步select count一次。

10多年前博客園ORM大戰(zhàn)的時候,我們常說,等你支持千萬級分頁的時候再來比,就是鉆了select count很慢的這個空子,很多人count出來總數(shù)再分頁?^_^

上圖4億數(shù)據(jù),查詢第10000頁,在SQLite單表上,阿里云1C1G服務器。

?

FindCount?分頁

在早期版本,不支持RetrieveTotalCount ,只能通過 FindCount 取得滿足該條件的總記錄數(shù),然后進行分頁,至今仍然支持傳統(tǒng)方法。

因此可以看到,FindAll 和 FindCount 都是成對出現(xiàn),參數(shù)一摸一樣。

并且 FindCount 方法也會帶有分頁參數(shù),雖然用不到,但.NET2.0時代的 ObjectDataSource 要求兩者的參數(shù)名稱和順序必須一致。

所有 FindCount 方法,將會得到 select count 查詢語句,因此千萬級大表需要慎用。

?

PageSplit?分頁

內(nèi)置支持的各種數(shù)據(jù)庫,都有實現(xiàn)普通查詢語句轉(zhuǎn)為分頁語句的 PageSplit(sql, start, maxNums) 方法。

MySql/SQLite/PostgreSQL 能夠很好支持,只需要在 sql 后加上 limit start, maxNums 即可;

Oracle/SqlServer/Access/SqlCe 則要麻煩一次,其中SqlServer最復雜,不同版本的分頁方法還不同,早期版本還要求有主鍵字段;

因此,sql 必須是簡單的單表查詢語句,PageSplit 才能把任意查詢拆開并轉(zhuǎn)換為分頁查詢。

?

大表分頁優(yōu)化

大表分頁查詢,開頭會很快,越是往后越慢!

XCode采用倒置優(yōu)化法,對于超過100萬行(借助Meta.Count評估)的表,如果查詢頁超過中線,則從另一個方向查詢,然后再把結果倒置回來。

?

?

XCode要求數(shù)據(jù)查詢必須考慮分頁,沒有分頁的系統(tǒng)一般死在100萬行以內(nèi)。

?

回到目錄

Field擴展

內(nèi)嵌類_引用的字段是Field,它繼承自FieldItem。

Field/FieldItem全部功能:

  • Equal?等于,操作符==

  • NotEqual?不等于,操作符!=

  • 大于操作符>,大于等于>=

  • 小于操作符<,小于等于<=

  • StartsWith 字符串開始,like '{0}%'。(支持索引)

  • EndsWith?字符串結束,like '%{0}'

  • Contains?字符串包含,like '%{0}%'

  • In?集合包含,支持列表集合、字符串子查詢和SelectBuilder子查詢,集合只有一個元素時轉(zhuǎn)為相等操作

  • NotIn?集合不包含,支持列表集合、字符串子查詢和SelectBuilder子查詢,集合只有一個元素時轉(zhuǎn)為不相等操作

  • IsNull?是否空

  • NotIsNull?不是空

  • IsNullOrEmpty?字符串空或零長度

  • NotIsNullOrEmpty?字符串非空非零長度

  • IsTrue?是否True或者False/Null,參數(shù)決定兩組之一

  • IsFalse?是否False或者True/Null,參數(shù)決定兩組之一

  • Between?時間區(qū)間,大于等于開始,小于結束,如果開始結束都只有日期而沒有時分秒,則結束加一天,如(2019-04-17,? 2019-04-17)查 time>='2019-04-17' and time<2019-04-18'

排序字句/分組聚合

  • Asc,升序

  • Desc,降序。order by name desc

  • GroupBy,分組。group by name

  • As,聚合別名

  • Count,計數(shù)

  • Sum,求和

  • Min,最小

  • Max,最大

?

回到目錄

查詢的本質(zhì)

查詢的本質(zhì)是五參數(shù)版FindAll(where, order, selects, start, maxnums),其它查詢方式都由它轉(zhuǎn)化而來!

Entity實體基類封裝了各種常用的查詢方法:

對于單表查詢的XCode來說,五參數(shù)版FindAll很容易得到?select [selects] from [table] where [where] order by [order] limit [start], [maxnums]?語句,根據(jù)這個理念,FindAll可以支持任意復雜查詢!

最終查詢語句,由SelectBuilder類承載。

?

回到目錄

多表子查詢

XCode不支持多表Join關聯(lián),這在前面《擴展屬性》中提到過。

擴展屬性固然可以解決關聯(lián)多表字段的問題,并且借助緩存性能還不錯,但是需要同時在兩張表上設置條件的時候,就行不通了。

于是,需要用到高級查詢,可以用子查詢 來替代,正是前面說到的FieldItem.In擴展。

?

要查詢名為“992班”的所有學生,一般這樣寫:

select * from student s inner join class c on s.classid=c.id where c.name='992班'

XCode從2008年起,就放棄支持多表關聯(lián),自然也就不支持這樣的寫法。

在一般系統(tǒng)里面,班級表數(shù)據(jù)不多,可以借助實體緩存或者對象緩存:

// Class.FindByName 內(nèi)部用緩存
var cls = Class.FindByName("992班");
var list = Student.FindAll(Student._.ClassID==cls.ID);
// select * from student where classid=1234

但如果主表從表都是百萬級大表,或者從表查詢條件比較復雜,緩存就有點難以為繼了。

于是有了子查詢:

調(diào)用方法:var list = Student.Search(SexKinds.女, "992班", p);

得到結果:

select * from student where sex=2 and classid in(select id from class where name='992班')

至此,絕大部分多表關聯(lián)復雜查詢語句,可以轉(zhuǎn)化為子查詢 !

?

回到目錄

系列教程

NewLife.XCode教程系列[2019版]

  • 增刪改查入門。快速展現(xiàn)用法,代碼配置連接字符串

  • 數(shù)據(jù)模型文件。建立表格字段和索引,名字以及數(shù)據(jù)類型規(guī)范,推薦字段(時間,用戶,IP)

  • 實體類詳解。數(shù)據(jù)類業(yè)務類,泛型基類,接口

  • 功能設置。連接字符串,調(diào)試開關,SQL日志,慢日志,參數(shù)化,執(zhí)行超時。代碼與配置文件設置,連接字符串局部設置

  • 反向工程。自動建立數(shù)據(jù)庫數(shù)據(jù)表

  • 數(shù)據(jù)初始化。InitData寫入初始化數(shù)據(jù)

  • 高級增刪改。重載攔截,自增字段,Valid驗證,實體模型(時間,用戶,IP)

  • 臟數(shù)據(jù)。如何產(chǎn)生,怎么利用

  • 增量累加。高并發(fā)統(tǒng)計

  • 事務處理。單表和多表,不同連接,多種寫法

  • 擴展屬性。多表關聯(lián),Map映射

  • 高級查詢。復雜條件,分頁,自定義擴展FieldItem,查總記錄數(shù),查匯總統(tǒng)計

  • 數(shù)據(jù)層緩存。Sql緩存,更新機制

  • 實體緩存。全表整理緩存,更新機制

  • 對象緩存。字典緩存,適用用戶等數(shù)據(jù)較多場景。

  • 百億級性能。字段精煉,索引完備,合理查詢,充分利用緩存

  • 實體工廠。元數(shù)據(jù),通用處理程序

  • 角色權限。Membership

  • 導入導出。Xml,Json,二進制,網(wǎng)絡或文件

  • 分表分庫。常見拆分邏輯

  • 高級統(tǒng)計。聚合統(tǒng)計,分組統(tǒng)計

  • 批量寫入。批量插入,批量Upsert,異步保存

  • 實體隊列。寫入級緩存,提升性能。

  • 備份同步。備份數(shù)據(jù),恢復數(shù)據(jù),同步數(shù)據(jù)

  • 數(shù)據(jù)服務。提供RPC接口服務,遠程執(zhí)行查詢,例如SQLite網(wǎng)絡版

  • 大數(shù)據(jù)分析。ETL抽取,調(diào)度計算處理,結果持久化

  • ?


    總結

    以上是生活随笔為你收集整理的[NewLife.XCode]高级查询(化繁为简、分页提升性能)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。