实测 Schema 校验:121 错误里 errInfo.details 逐条说明哪条规则没通过;validationAction 为 warn 时照样写入并在日志里记警告;validationLevel 的 strict 与 moderate 对不合法的老文档的区别;bypassDocumentValidation 与 off;$expr 校验器;insertMany 在 ordered 与 unordered 下的行为。
实测 collation:默认二进制比较,strength 2 忽略大小写、strength 1 连重音也忽略,numericOrdering 与 zh 拼音排序;collation 查询用不上不带 collation 的索引(全表检查 200,000 个文档),建同 collation 的索引后只检查 1 个;正则 /i 比全表 collation 更慢;集合级默认 collation 与索引变大 17%。
在本机测试服务器(每个请求停 0.1 秒)上对比线程池 requests 与 asyncio aiohttp:并发 10 到 100 时都紧贴理论下限,并发 200 时 698 ms 对 615 ms;无延迟时每请求 0.331 ms 对 0.109 ms;并发 200 的峰值内存比起点多 18.8 MiB 对 3.3 MiB。
实测 asyncio 信号量限制爬虫并发:Semaphore(N) 让服务器看到的并发峰值恰好是 N;但只包住 session.get() 而不包住读取响应体时,Semaphore(5) 的实际并发是 50;TCPConnector(limit=10) 加 total 超时让 200 个请求中 110 个超时,改用 Semaphore 排队则 0 个;20 万个任务 gather 要 310.8 MiB,worker 加队列 23.5 MiB。
同一条查询在 explain 的三种模式下看到的信息:queryPlanner 只选计划不执行,executionStats 执行并给出键数、文档数和每个阶段的 works,allPlansExecution 再给出落选计划的试跑统计;update / delete 的 explain 不修改数据;aggregate 的 pipeline 被整个下推并成为覆盖查询。
实测复合索引字段顺序(等值、排序、范围):有 limit 20 时 E-S-R 只检查 195 个键最快,不 limit 时 E-S-R 要扫 60,001 个键而 E-R-S 只要 6000 个,反而 E-R-S 更快;优化器无 limit 时仍选了 E-S-R;范围换成等值后等值字段全放前面才是最优。
实测 aiohttp 的 TCPConnector:默认 limit=100、limit_per_host=0,对单个站点最多同时开 100 条连接;limit 是总数上限、limit_per_host 是每个主机的上限,两个都设时更紧的生效;“主机”按主机名区分(4 个域名指向同一台服务器时对方看到 20 个并发);多个 ClientSession 的 limit 会叠加(3 个会话峰值 30)。
实测覆盖查询:投影去掉 _id 且字段都在索引里时 totalDocsExamined 为 0;带 _id、取索引外字段、条件里有索引外字段、数组(multikey)字段都要 FETCH;把 _id 放进索引后带 _id 也能覆盖;count 与 $group 也能覆盖。
用心跳任务测 asyncio 事件循环被卡的时间:20 个页面抓完后直接在协程里用 lxml 解析,事件循环最大延迟 1293 ms;放进线程池后降到 15 ms 但总耗时几乎不变(1518 ms),进程池才真正并行(557 ms);协程里直接 requests.get 让 10 个“并发”请求变成串行(1079 ms,服务器峰值 1)。
实测多键索引:数组每个元素一条索引条目(空数组、缺失、标量各 1 条,同一文档内重复元素去重),条目数和索引大小随数组长度线性增长(100 个元素时每个文档 884 字节),$elemMatch 比普通条件界限更紧,写入代价随元素数线性增长。
实测两个数组字段的复合索引:同一文档里最多一个被索引字段是数组,两个都是数组时插入、更新报 171(cannot index parallel arrays),已有这种文档时建索引失败;同一数组的两个子字段不算并行;拆成单字段索引或展开成子文档数组两种办法的检查键数对比。
实测把 HTML 解析放进进程池:池冷启动 83 ms、预热后一个任务来回 0.141 ms;6 KB 到 2.5 MB 的页面 8 个进程都比直接解析快 5.3–6.2 倍,8 个线程基本不加速;传输页面的成本远小于解析;lxml 树不能返回;map 的 chunksize=1 只快 1.29 倍,批量后 6.15 倍。