乐于分享
好东西不私藏

AI 时代重学 PostgreSQL 实战:从 OFFSET 到 Keyset Pagination

AI 时代重学 PostgreSQL 实战:从 OFFSET 到 Keyset Pagination

后端写列表接口,最常见的参数是:

page=1&page_size=20

然后 SQL 很自然:

SELECT *FROM postsORDER BY created_at DESCLIMIT 20 OFFSET 0;

第一页没问题。

第十页也没问题。

到第一千页,问题就来了:

LIMIT 20 OFFSET 20000

很多人对 OFFSET 的理解是:“数据库直接跳到第 20001 条,然后取 20 条。”

但数据库不是这么工作的。

更接近真实情况的是:它要按排序顺序找到前 20020 条,然后丢掉前 20000 条,把最后 20 条返回给你。

这就是 OFFSET 越翻越慢的根本原因。

完整代码在 postgres-keyset-pagination-lab[1]。这篇文章里的代码都来自这个仓库。

先别急着骂数据库。

OFFSET 的语义本来就是“跳过多少行”。

SELECT id, title, created_atFROM keyset_lab_postsWHERE status = 'published'ORDER BY created_at DESC, id DESCLIMIT 20 OFFSET 20000;

即使有索引,PostgreSQL 也不能凭空知道“第 20001 条”在哪里。它仍然要沿着排序结果往后走,跳过前面的 20000 行。

有索引时,它可能走索引扫描。

没索引时,它可能排序后再跳。

但不管执行计划怎么变,OFFSET N 的语义决定了它必须处理被跳过的那一段。

所以 OFFSET 的成本会随着页码变大而变大。

这不是 bug,是语义。

先建一张实验表

实验里只有一张 posts 表:

CREATE TABLE keyset_lab_posts (    id         BIGSERIAL PRIMARY KEY,    title      TEXT NOT NULL,    status     TEXT NOT NULL,    created_at TIMESTAMPTZ NOT NULL);

索引很关键:

CREATE INDEX keyset_lab_posts_created_id_idxON keyset_lab_posts (created_at DESC, id DESC);

这里故意用 (created_at, id) 两个字段。

如果只用 created_at 排序,会有一个问题:同一秒内可能有多条记录。排序不唯一,分页边界就不稳定。

所以我们加上 id 作为 tie-breaker:

ORDER BY created_at DESC, id DESC

这句话的意思是:

  • • 新的排前面。
  • • created_at 一样时,id 大的排前面。

分页必须有稳定顺序。没有稳定顺序,就不要谈稳定分页。

OFFSET 版本怎么写

代码很普通:

func ListOffset(ctx context.Context, pool *pgxpool.Pool, limit int, offset int) (Page, error) {    if limit <= 0 {        limit = 20    }    if offset < 0 {        offset = 0    }    start := time.Now()    rows, err := pool.Query(ctx, `SELECT id, title, created_atFROM keyset_lab_postsWHERE status = &#x27;published&#x27;ORDER BY created_at DESC, id DESCLIMIT $1 OFFSET $2`, limit, offset)    if err != nil {        return Page{}, fmt.Errorf("list offset: %w", err)    }    defer rows.Close()    items, err := scanPosts(rows)    if err != nil {        return Page{}, err    }    return Page{Items: items, Elapsed: time.Since(start)}, nil}

运行:

go run ./cmd/offset

输出类似:

mode=offset limit=20 offset=20000 rows=20 elapsed=3.671084msfirst_id=20001 last_id=20020

本地 30000 条数据,几毫秒还不吓人。

但这个实验重点不是“几毫秒”,而是查询形状:offset 越大,数据库要跳过的行越多。

如果是几百万、几千万行,或者列表查询还带复杂过滤、join、权限条件,这个成本会变得很明显。

OFFSET 还有一个稳定性问题

性能只是一个问题。

OFFSET 还有一个更容易被忽略的问题:列表会漂。

假设现在第一页是:

1, 2, 3, 4, 5

用户看完第一页,准备请求第二页:

OFFSET 5 LIMIT 5

就在这中间,有人插入了一条新数据,排到了最前面:

new, 1, 2, 3, 4, 5

这时 OFFSET 5 跳过的是:

new, 1, 2, 3, 4

第二页第一条变成 5

用户会重复看到 5

删除也类似,可能漏数据。

所以 OFFSET 不只是“慢”,它还不适合高频变化的信息流、推荐流、消息列表、订单流水这类场景。

Keyset 的思路

Keyset pagination 不问“第几页”。

它问的是:

上一页最后一条是谁?从它后面继续取。

比如第一页最后一条是:

created_at = 2026-05-17 10:00:00id = 100

下一页就查:

SELECT id, title, created_atFROM keyset_lab_postsWHERE status = &#x27;published&#x27;  AND (created_at, id) < ($1, $2)ORDER BY created_at DESC, id DESCLIMIT 20;

这里的 (created_at, id) < ($1, $2) 是 PostgreSQL 的行构造比较。

因为我们的排序是:

ORDER BY created_at DESC, id DESC

所以“下一页”就是:

  • • created_at 更早。
  • • 或者 created_at 相同但 id 更小。

这个条件正好能用复合索引:

CREATE INDEX keyset_lab_posts_created_id_idxON keyset_lab_posts (created_at DESC, id DESC);

Keyset 版本怎么写

先定义返回结构:

type Post struct {    ID        int64    Title     string    CreatedAt time.Time}type Page struct {    Items      []Post    NextCursor *Cursor    Elapsed    time.Duration}

核心查询:

func ListKeyset(ctx context.Context, pool *pgxpool.Pool, limit int, cursor *Cursor) (Page, error) {    if limit <= 0 {        limit = 20    }    start := time.Now()    var (        rows pgx.Rows        err  error    )    if cursor == nil {        rows, err = pool.Query(ctx, `SELECT id, title, created_atFROM keyset_lab_postsWHERE status = &#x27;published&#x27;ORDER BY created_at DESC, id DESCLIMIT $1`, limit)    } else {        rows, err = pool.Query(ctx, `SELECT id, title, created_atFROM keyset_lab_postsWHERE status = &#x27;published&#x27;  AND (created_at, id) < ($1, $2)ORDER BY created_at DESC, id DESCLIMIT $3`, cursor.CreatedAt, cursor.ID, limit)    }    if err != nil {        return Page{}, fmt.Errorf("list keyset: %w", err)    }    defer rows.Close()    items, err := scanPosts(rows)    if err != nil {        return Page{}, err    }    var next *Cursor    if len(items) > 0 {        last := items[len(items)-1]        next = &Cursor{CreatedAt: last.CreatedAt, ID: last.ID}    }    return Page{Items: items, NextCursor: next, Elapsed: time.Since(start)}, nil}

第一页没有 cursor。

从第二页开始,带上上一页最后一条记录的 (created_at, id)

这就是 keyset 的核心。

cursor 不能直接暴露成两个参数吗

当然可以。

比如:

?created_at=2026-05-17T10:00:00Z&id=100

但 API 一般会包装成一个 cursor 字符串。

实验代码里用 JSON + base64:

type Cursor struct {    CreatedAt time.Time `json:"created_at"`    ID        int64     `json:"id"`}func EncodeCursor(cursor Cursor) (string, error) {    payload, err := json.Marshal(cursor)    if err != nil {        return "", fmt.Errorf("marshal cursor: %w", err)    }    return base64.RawURLEncoding.EncodeToString(payload), nil}func DecodeCursor(raw string) (Cursor, error) {    payload, err := base64.RawURLEncoding.DecodeString(raw)    if err != nil {        return Cursor{}, fmt.Errorf("decode cursor: %w", err)    }    var cursor Cursor    if err := json.Unmarshal(payload, &cursor); err != nil {        return Cursor{}, fmt.Errorf("unmarshal cursor: %w", err)    }    if cursor.ID <= 0 || cursor.CreatedAt.IsZero() {        return Cursor{}, fmt.Errorf("invalid cursor")    }    return cursor, nil}

注意:base64 不是加密。

它只是让 cursor 更适合放进 URL。

如果你不希望客户端篡改 cursor,可以加签名:

base64(json_payload) + "." + hmac_sha256(payload, secret)

但大多数后台列表场景,先把 cursor 解析和参数校验做好就够了。

跑一次 keyset

运行:

go run ./cmd/keyset

输出类似:

first_page rows=10 first_id=1 last_id=10 elapsed=1.456583msnext_cursor=eyJjcmVhdGVkX2F0IjoiMjAyNi0wNS0xN1QxMTo0NToyMS43OTg1OTkrMDg6MDAiLCJpZCI6MTB9second_page rows=10 first_id=11 last_id=20 elapsed=814.666µs

你不用关心 cursor 里面具体长什么样。

客户端只要把 next_cursor 原样带回来:

GET /posts?limit=10&cursor=eyJjcmVhdGVkX2F0...

服务端 decode 之后继续查下一页。

OFFSET 和 Keyset 对比

为了让对比更直观,实验里有一个 compare 命令。

它先用 OFFSET 查第 20001 条开始的 20 条:

const depth = 20000offsetPage, err := pagination.ListOffset(ctx, pool, 20, depth)if err != nil {    log.Fatal(err)}

然后构造同一位置的 cursor:

cursor, err := pagination.CursorAtOffset(ctx, pool, depth-1)if err != nil {    log.Fatal(err)}keysetPage, err := pagination.ListKeyset(ctx, pool, 20, &cursor)if err != nil {    log.Fatal(err)}

这里 CursorAtOffset 只是为了实验对齐,不是生产写法。生产环境里 cursor 来自上一页最后一条。

运行:

go run ./cmd/compare

输出类似:

offset rows=20 elapsed=3.651375ms first_id=20001 last_id=20020keyset rows=20 elapsed=1.381167ms first_id=20001 last_id=20020

本地数据量小,差距不会特别夸张。

但查询形状已经不一样了。

OFFSET 是:

ORDER BY created_at DESC, id DESCLIMIT 20 OFFSET 20000

Keyset 是:

WHERE (created_at, id) < ($1, $2)ORDER BY created_at DESC, id DESCLIMIT 20

前者要跳过一段。

后者从边界继续往后扫。

Keyset 的几个硬规则

Keyset 不是把 OFFSET 改成 WHERE id < ? 就完了。

我会按下面几条检查。

排序必须稳定。

不要只写:

ORDER BY created_at DESC

要写:

ORDER BY created_at DESC, id DESC

如果排序字段可能重复,就必须加唯一字段兜底。

cursor 字段必须和 ORDER BY 对齐。

排序是 (created_at DESC, id DESC),cursor 也必须带 created_at 和 id

如果排序是 (score DESC, created_at DESC, id DESC),cursor 就要带这三个字段。

不要 ORDER BY 三个字段,cursor 只存一个字段。

比较方向要和排序方向一致。

DESC 下一页通常用 <

AND (created_at, id) < ($1, $2)

ASC 下一页通常用 >

AND (created_at, id) > ($1, $2)

如果有混合排序,比如 score DESC, id ASC,就不要偷懒用行比较,老老实实写展开条件。

cursor 字段最好 NOT NULL。

行比较遇到 NULL 会变麻烦。

分页字段如果允许 NULL,你要明确 NULL 排前还是排后,并写清楚条件。大多数业务列表里,created_atid 这种字段就应该是 NOT NULL。

Keyset 的代价

Keyset 不是银弹。

它有几个代价必须提前接受。

第一,它不适合随机跳页。

如果产品强需求是“跳到第 100 页”,OFFSET 更直接。Keyset 的思路是“从当前页继续往后翻”。

所以它更适合:

  • • feed 流。
  • • 消息列表。
  • • 订单流水。
  • • 操作日志。
  • • 搜索结果的下一页。
  • • 后台无限滚动列表。

不太适合:

  • • 明确要显示第 1/2/3/4 页的传统分页器。
  • • 要快速跳到任意页码的报表。

第二,总数不天然便宜。

很多接口喜欢返回:

{  "total": 1234567,  "items": []}

大表上每次都 COUNT(*),也可能很贵。

Keyset 通常返回的是:

{  "items": [],  "next_cursor": "..."}

如果业务一定要 total,可以异步算、缓存、估算,或者只在筛选条件很小的时候算。

第三,排序条件变了,cursor 就失效。

用户第一页按“最新”排序,第二页切成“最热”,旧 cursor 不能继续用。

所以 cursor 最好绑定查询条件:

filter_hash + sort_key + cursor_payload

至少服务端要知道这个 cursor 是在哪个排序和筛选条件下生成的。

真实接口我会怎么返回

一个比较干净的响应结构是:

{  "items": [    {      "id": 1,      "title": "post-1",      "created_at": "2026-05-17T10:00:00Z"    }  ],  "next_cursor": "eyJjcmVhdGVkX2F0Ijoi..."}

请求下一页:

GET /posts?limit=20&cursor=eyJjcmVhdGVkX2F0Ijoi...

如果已经到末页,可以返回:

{  "items": [    {      "id": 100,      "title": "post-100",      "created_at": "2026-05-17T09:00:00Z"    }  ],  "next_cursor":null}

实验代码里只要 len(items) > 0 就生成 cursor:

var next *Cursorif len(items) > 0 {    last := items[len(items)-1]    next = &Cursor{CreatedAt: last.CreatedAt, ID: last.ID}}

生产里我更常用 limit + 1

LIMIT page_size + 1

如果多取到一条,说明还有下一页。

返回时丢掉多出来的那一条,并用当前返回列表最后一条生成 cursor。

这样 next_cursor 才能准确表达“还有下一页”。

和上一篇 Outbox 的共同点

表面看,Outbox 和 Keyset 没关系。

一个是可靠事件投递。

一个是分页性能。

但它们背后有同一个思路:不要用看起来简单的 API 掩盖真实语义。

db.Commit(); mq.Publish() 看起来简单,但中间有崩溃窗口。

LIMIT 20 OFFSET 20000 看起来简单,但数据库要跳过 20000 行,列表还会因为插入删除漂移。

后端工程很多坑不是“不会写语法”,而是没有把语义想完。

最后给一个选择标准

我一般这么判断:

后台低频管理页,页数不深。

用 OFFSET 可以。它简单,产品也容易理解。

用户端信息流、订单流水、消息列表。

优先 Keyset。用户通常只需要继续往下翻,不需要跳第 100 页。

数据变化频繁。

优先 Keyset。它能减少重复和漏读。

排序字段不稳定,或者业务必须随机跳页。

别硬套 Keyset。先把产品交互和查询语义讲清楚。

OFFSET 不是错。

错的是明明在做无限滚动、深翻页和高频变化列表,却还把 page/page_size 当成唯一方案。

分页不是两个参数。

分页是排序、边界和一致性的设计。

引用链接

[1] postgres-keyset-pagination-lab: https://github.com/arixbit/postgres-keyset-pagination-lab

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-06-14 22:39:35 HTTP/1.1 GET : https://www.yeyulingfeng.com/a/749506.html
  2. 运行时间 : 0.101506s [ 吞吐率:9.85req/s ] 内存消耗:4,645.55kb 文件加载:145
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=f21d6727ba5710993edd341e096bb44e
  1. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_static.php ( 6.05 KB )
  7. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/ralouphie/getallheaders/src/getallheaders.php ( 1.60 KB )
  10. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  11. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  12. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  13. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  14. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  15. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  16. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  17. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  18. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  19. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions_include.php ( 0.16 KB )
  21. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions.php ( 5.54 KB )
  22. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  23. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  24. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  25. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/provider.php ( 0.19 KB )
  26. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  27. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  28. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  29. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/common.php ( 0.03 KB )
  30. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  32. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/alipay.php ( 3.59 KB )
  33. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  34. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/app.php ( 0.95 KB )
  35. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cache.php ( 0.78 KB )
  36. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/console.php ( 0.23 KB )
  37. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cookie.php ( 0.56 KB )
  38. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/database.php ( 2.48 KB )
  39. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/filesystem.php ( 0.61 KB )
  40. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/lang.php ( 0.91 KB )
  41. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/log.php ( 1.35 KB )
  42. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/middleware.php ( 0.19 KB )
  43. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/route.php ( 1.89 KB )
  44. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/session.php ( 0.57 KB )
  45. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/trace.php ( 0.34 KB )
  46. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/view.php ( 0.82 KB )
  47. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/event.php ( 0.25 KB )
  48. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  49. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/service.php ( 0.13 KB )
  50. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/AppService.php ( 0.26 KB )
  51. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  52. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  53. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  54. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  55. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  56. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/services.php ( 0.14 KB )
  57. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  58. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  59. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  60. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  61. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  62. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  63. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  64. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  65. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  66. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  67. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  68. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  69. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  70. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  71. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  72. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  73. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  74. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  75. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  76. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  77. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  78. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  79. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  80. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  81. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  82. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  83. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  84. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  85. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  86. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  87. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/Request.php ( 0.09 KB )
  88. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  89. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/middleware.php ( 0.25 KB )
  90. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  91. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  92. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  93. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  94. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  95. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  96. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  97. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  98. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  99. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  100. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  101. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  102. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  103. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/route/app.php ( 3.94 KB )
  104. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  105. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  106. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Index.php ( 9.87 KB )
  108. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/BaseController.php ( 2.05 KB )
  109. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  110. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  111. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  112. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  113. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  114. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  115. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  116. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  117. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  118. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  119. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  120. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  121. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  122. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  123. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  124. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  125. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  126. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  127. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  128. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  129. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  130. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  131. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  132. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  133. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  134. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  135. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Es.php ( 3.30 KB )
  136. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  137. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  138. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  139. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  140. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  141. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  142. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  143. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  144. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/runtime/temp/c935550e3e8a3a4c27dd94e439343fdf.php ( 31.50 KB )
  145. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000506s ] mysql:host=127.0.0.1;port=3306;dbname=wenku;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000640s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000273s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.001744s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000603s ]
  6. SELECT * FROM `set` [ RunTime:0.000284s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000606s ]
  8. SELECT * FROM `article` WHERE `id` = 749506 LIMIT 1 [ RunTime:0.002049s ]
  9. UPDATE `article` SET `lasttime` = 1781447975 WHERE `id` = 749506 [ RunTime:0.003804s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 64 LIMIT 1 [ RunTime:0.000329s ]
  11. SELECT * FROM `article` WHERE `id` < 749506 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000451s ]
  12. SELECT * FROM `article` WHERE `id` > 749506 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000501s ]
  13. SELECT * FROM `article` WHERE `id` < 749506 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.001582s ]
  14. SELECT * FROM `article` WHERE `id` < 749506 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.003581s ]
  15. SELECT * FROM `article` WHERE `id` < 749506 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.005349s ]
0.103143s