{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 实验 04：位图索引与 Bloom 过滤器 —— 把 WHERE 子句变成位运算\n",
    "\n",
    "## 为什么做这个实验\n",
    "\n",
    "`WHERE` 子句一定要逐行判断吗？本实验给出另一条路：把每个谓词变成一条**位序列**（第 j 位表示第 j 行是否满足该谓词），于是 `AND / OR / NOT` 可以直接用 CPU 的位运算一次处理整列。\n",
    "\n",
    "反直觉的地方有三处。\n",
    "\n",
    "1. **同一份位图，换个物理表示性能能差两个数量级。** \"布尔列表\"和\"Python 大整数\"表达的信息完全一样，但前者要在 Python 层循环 N 次，后者是一条覆盖 N 位的机器指令。\n",
    "2. **压缩位图省了空间，查询却可能更慢。** 运算前要先把压缩格式解析开——空间和时间不是一起变好的。\n",
    "3. **Bloom 过滤器用几十个位就能挡掉绝大多数回盘，代价是它会说谎。** 但它只会说一种谎：**有假阳性，永远没有假阴性**。返回\"不在\"就一定不在，返回\"可能在\"才需要回原始数据复核。\n",
    "\n",
    "做完这个实验，你应该能回答：什么时候值得建位图索引（提示：看\"取值个数 × 行数\"这个乘积）？范围查询该用等值编码还是范围编码？以及给定可接受的错误率，Bloom 过滤器该配多少位、几个哈希函数（$k^* = (m/n)\\ln 2$、$m = -n \\ln p / (\\ln 2)^2$）。\n",
    "\n",
    "## 运行前准备\n",
    "\n",
    "1. Python 3.10 及以上。\n",
    "2. 安装依赖（在仓库根目录执行）：\n",
    "\n",
    "   ```bash\n",
    "   pip install numpy matplotlib jupyter\n",
    "   ```\n",
    "\n",
    "   `pandas` 只用于把输出表格化，可选。验证方式：\n",
    "\n",
    "   ```python\n",
    "   import numpy, matplotlib\n",
    "   print(\"环境 OK\")\n",
    "   ```\n",
    "\n",
    "3. 必须**从仓库根目录**（其下有 `system/` 与 `notebooks/`）启动 Jupyter，否则下一格的 `from system.bit_sequences import ...` 会报 `ModuleNotFoundError`：\n",
    "\n",
    "   ```bash\n",
    "   jupyter notebook notebooks/Bitmaps-and-Bloom-Filters.ipynb\n",
    "   ```\n",
    "\n",
    "4. 本笔记本会在工作目录写一个临时文件 `addresses.pkl`（用来模拟\"磁盘上的数据\"），跑完可以自行删除。"
   ],
   "id": "c4871573"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys, pathlib\n",
    "\n",
    "# Put the repo root (the directory containing `system/`) on sys.path so\n",
    "# `from system...` works whether this notebook is opened from its own\n",
    "# folder or from the repo root.\n",
    "for _p in (pathlib.Path.cwd(), *pathlib.Path.cwd().parents):\n",
    "    if (_p / \"system\").is_dir():\n",
    "        if str(_p) not in sys.path:\n",
    "            sys.path.insert(0, str(_p))\n",
    "        break"
   ],
   "id": "9540e283-fe9f-48cc-8422-51c47745ea1b"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-07T15:40:10.010260Z",
     "start_time": "2025-01-07T15:40:09.681720Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from system.data_classes import Address\n",
    "import statistics\n",
    "import time\n",
    "import itertools as it\n",
    "from system.bit_sequences import IntegerBitSequence, BitListBitSequence, WAHBitSequence\n",
    "from system.interfaces.bit_sequence import (\n",
    "    BitSequence,\n",
    "    UncompressedBitSequence,\n",
    "    CompressedBitSequence,\n",
    ")\n",
    "from system.indexes.bloom_filters import BloomFilter\n",
    "from system.indexes.bitmap_indexes import (\n",
    "    SortedEqualityEncodedBitmapIndex,\n",
    "    RangeEncodedBitmapIndex,\n",
    ")\n",
    "import pickle\n",
    "from typing import Type\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np"
   ],
   "id": "8805f6eda12672d3",
   "outputs": [],
   "execution_count": 1
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 一、数据准备：一张 4 000 行的地址表\n",
    "\n",
    "每个地址有三个属性：`city`（4 个取值）、`street`（5 个取值）、`house_number`（1～200），用 `itertools.product` 做笛卡尔积，得到 $4 \\times 5 \\times 200 = 4000$ 条记录，`id` 从 0 递增。\n",
    "\n",
    "属性这么少不是偷懒，而是**位图索引的适用前提**：位图索引的总空间是\n",
    "\n",
    "$$\\text{总位数} = \\text{取值个数} \\times \\text{行数}$$\n",
    "\n",
    "取值个数（基数）一高，空间就爆炸。所以位图索引用在\"性别、城市、状态码\"这类低基数列上；主键这种 100% 唯一的列，要用 B+ 树或哈希索引。\n",
    "\n",
    "最后三个 `*_bulkload_generator()` 是给索引用的喂数器，逐个产出 `(属性值, 行号)` 对。改 `possible_house_numbers` 的 `range(1, 201)` 可以同时调行数和基数——这是本笔记本唯一的规模旋钮。"
   ],
   "id": "abf30a64"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-07T15:40:10.022379Z",
     "start_time": "2025-01-07T15:40:10.011321Z"
    }
   },
   "cell_type": "code",
   "source": "# Four possible cities\npossible_cities: list[str] = [\"New York\", \"Cuppertino\", \"Berlin\", \"Saarbrücken\"]\n\n# Five possible streets\npossible_streets: list[str] = [\n    \"Unistreet\",\n    \"Macstreet\",\n    \"Longstreet\",\n    \"Msstreet\",\n    \"BigDataStreet\",\n]\n\n# Possible house numbers. This is the size knob for the whole notebook: the\n# number of addresses is len(cities) * len(streets) * len(house_numbers), and it\n# drives every index build -- in particular the range-encoded index, which\n# creates one bit-sequence per distinct house number. We cap it at 200 (-> 4000\n# addresses) to keep CI fast (~4s instead of ~19s); the relative comparisons and\n# plots stay representative. For the lecture, uncomment the range(1, 1001) line.\npossible_house_numbers: list[int] = list(range(1, 201))\n# possible_house_numbers: list[int] = [i for i in range(1, 1001)]\n\n# Create all combinations (len(cities) * len(streets) * len(house_numbers)) of addresses\nall_addresses: list[Address] = []\nfor idx, comb in enumerate(\n    it.product(possible_cities, possible_streets, possible_house_numbers)\n):\n    all_addresses.append(Address(idx, comb[0], comb[1], comb[2]))\n\n\n# Create bulkloads to be used for different indexes\ndef city_bulkload_generator():\n    yield from ((address.city, address.id) for address in all_addresses)\n\n\ndef street_bulkload_generator():\n    yield from ((address.street, address.id) for address in all_addresses)\n\n\ndef house_number_bulkload_generator():\n    yield from ((address.house_number, address.id) for address in all_addresses)",
   "id": "f1079e59c8d5c5f4",
   "outputs": [],
   "execution_count": null
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 二、第一个查询：把 WHERE 变成位运算\n",
    "\n",
    "假设要查\"在纽约、且街道是 Unistreet 或 BigDataStreet\"的地址：\n",
    "\n",
    "```sql\n",
    "SELECT COUNT(*)\n",
    "FROM   addresses\n",
    "WHERE  city = 'New York' AND (street = 'Unistreet' OR street = 'BigDataStreet')\n",
    "```\n",
    "\n",
    "翻译成位运算只有一行：\n",
    "\n",
    "```text\n",
    "city['New York']  &  ( street['Unistreet'] | street['BigDataStreet'] )\n",
    "```\n",
    "\n",
    "其中 `city['New York']` 是一条长度 4000 的位序列，第 j 位为 1 表示第 j 行在纽约。\n",
    "\n",
    "| SQL 逻辑 | 位运算 | Python 写法 |\n",
    "| --- | --- | --- |\n",
    "| `p AND q` | 按位与 | `a & b` |\n",
    "| `p OR q` | 按位或 | `a \\| b` |\n",
    "| `NOT p` | 按位取反 | `~a` |\n",
    "| `p AND NOT q` | 与非 | `a & ~b` |\n",
    "\n",
    "先看看最朴素的做法要花多久。"
   ],
   "id": "7990fde5"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 朴素执行：逐行判断\n",
    "\n",
    "把 4000 条地址遍历一遍，对每条做字符串比较，把命中的 `id` 收进集合。\n",
    "\n",
    "这段代码没有任何技巧可言，它的作用只有一个：**给出正确答案和基线耗时**，后面所有索引方案的结果都必须和它对得上（笔记本最后一节的单元测试就是在做这件事）。"
   ],
   "id": "be6a7701"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-07T15:40:10.052988Z",
     "start_time": "2025-01-07T15:40:10.023103Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# Store the results of the query above\n",
    "query_1_naive_result: set[int] = set()\n",
    "\n",
    "start = time.time()\n",
    "\n",
    "for address in all_addresses:\n",
    "    # Make String comparisons\n",
    "    if address.city == \"New York\" and (\n",
    "        address.street in (\"Unistreet\", \"BigDataStreet\")\n",
    "    ):\n",
    "        query_1_naive_result.add(address.id)\n",
    "\n",
    "end = time.time()\n",
    "print(f\"Time taken for naive query: {end - start}\")\n",
    "print(f\"The number of corresponding ids is: {len(query_1_naive_result)}\")"
   ],
   "id": "a5432792186ce53f",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Time taken for naive query: 0.0008704662322998047\n",
      "The number of corresponding ids is: 2000\n"
     ]
    }
   ],
   "execution_count": 3
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "结果是对的，命中 **400** 条（可以手算验证：纽约占 1/4，两条目标街道占 2/5，$4000 \\times \\frac14 \\times \\frac25 = 400$）。\n",
    "\n",
    "本机实测朴素执行约 **0.2 ～ 0.4 ms**（单次运行波动明显，建议同一格重跑几次）。这个数字太小，说明**这份数据根本不足以体现索引的价值**——4000 行的循环在 Python 里也就是几十万次操作。\n",
    "\n",
    "所以本节的重点不是\"位图快多少\"，而是把三种实现的**相对关系**看清楚。真正的量级差距请对照本节末尾的 50 万行口径表基准。\n",
    "\n",
    "一个必须提醒自己的问题：**索引是要先花钱建的。** 建索引要扫一遍全表，之后每次查询才便宜。所以\"该不该建索引\"是个算术问题，不是信仰问题——本节末尾会给出回本公式。"
   ],
   "id": "8976bce9"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 等值编码位图索引\n",
    "\n",
    "**等值编码（equality encoding）**给属性的每个取值配一条位序列：\n",
    "\n",
    "$$E_i[j] = 1 \\iff A[j] = v_i$$\n",
    "\n",
    "于是查 `city = 'New York'` 只需取出对应的那一条位序列，不必碰数据。\n",
    "\n",
    "下面这一格定义了一个通用函数 `create_indexes_and_execute_query`，它做四件事并返回四个值：\n",
    "\n",
    "1. `bulkload` 建立 city 和 street 两个等值编码索引（用哪种位序列实现由参数 `bit_sequence_type` 决定）；\n",
    "2. 从索引里取出三条位序列；\n",
    "3. 用 `&` 和 `|` 组合出结果——**查询逻辑就在这一行**；\n",
    "4. 记录建索引耗时、查询耗时、占用位数、命中集合。\n",
    "\n",
    "注意函数签名里的 `compression_type`：它让我们可以用同一份查询逻辑去测\"压缩过的位序列\"，这正是第五节要干的事。"
   ],
   "id": "b3ebf950"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-07T15:40:10.069738Z",
     "start_time": "2025-01-07T15:40:10.054461Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def create_indexes_and_execute_query(\n",
    "    bit_sequence_type: Type[UncompressedBitSequence],\n",
    "    compression_type: Type[CompressedBitSequence] | None = None,\n",
    "    print_info=True,\n",
    "):\n",
    "    \"\"\"\n",
    "    Execute the query from above using different bitmap index implementations.\n",
    "    :param bit_sequence_type: The type of bit-sequence to use.\n",
    "    :param compression_type: The type of compression to use. None if no compression should be used.\n",
    "    :param print_info: Print information about different metrics.\n",
    "    :return: (The time to create an index, the time to execute the query, the number of bits stored in the index)\n",
    "    \"\"\"\n",
    "\n",
    "    start_index = time.time()\n",
    "\n",
    "    # Create Bitmap index for city\n",
    "    city_bitmap_index: SortedEqualityEncodedBitmapIndex = (\n",
    "        SortedEqualityEncodedBitmapIndex(\n",
    "            bit_sequence_type=bit_sequence_type, compression_type=compression_type\n",
    "        )\n",
    "    )\n",
    "    city_bitmap_index.bulkload(city_bulkload_generator())\n",
    "\n",
    "    # Create Bitmap index for street\n",
    "    street_bitmap_index: SortedEqualityEncodedBitmapIndex = (\n",
    "        SortedEqualityEncodedBitmapIndex(\n",
    "            bit_sequence_type=bit_sequence_type, compression_type=compression_type\n",
    "        )\n",
    "    )\n",
    "    street_bitmap_index.bulkload(street_bulkload_generator())\n",
    "    end_index = time.time()\n",
    "\n",
    "    start_exec = time.time()\n",
    "\n",
    "    # Get a bit_sequence containing all addresses in New York\n",
    "    street_equal_new_york: BitSequence = city_bitmap_index.get_equal(\"New York\")\n",
    "\n",
    "    # Get a bit_sequence containing all addresses in Unistreet\n",
    "    street_equal_unistreet: BitSequence = street_bitmap_index.get_equal(\"Unistreet\")\n",
    "\n",
    "    # Get a bit_sequence containing all addresses in BigDataStreet\n",
    "    street_equal_bigdatastreet: BitSequence = street_bitmap_index.get_equal(\n",
    "        \"BigDataStreet\"\n",
    "    )\n",
    "\n",
    "    # Combine results via bit operations\n",
    "    result: BitSequence = street_equal_new_york & (\n",
    "        street_equal_unistreet | street_equal_bigdatastreet\n",
    "    )\n",
    "    end_exec = time.time()\n",
    "    if print_info:\n",
    "        print(f\"\\tMeasure performance for index of type {bit_sequence_type}\")\n",
    "        print(f\"\\t\\tTime taken for creating an index: {end_index - start_index}\")\n",
    "        print(\n",
    "            f\"\\t\\tStored bits for the index: {city_bitmap_index.get_number_of_bits() + street_bitmap_index.get_number_of_bits()}\"\n",
    "        )\n",
    "        print(f\"\\t\\tTime taken for indexed query: {end_exec - start_exec}\")\n",
    "        print(f\"\\t\\tThe number of corresponding ids is: {len(result.as_set())}\")\n",
    "    return (\n",
    "        end_index - start_index,\n",
    "        end_exec - start_exec,\n",
    "        city_bitmap_index.get_number_of_bits()\n",
    "        + street_bitmap_index.get_number_of_bits(),\n",
    "        result.as_set(),\n",
    "    )"
   ],
   "id": "4f9d9d138c0dec6b",
   "outputs": [],
   "execution_count": 4
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 位序列该用什么结构存？\n",
    "\n",
    "索引逻辑是一样的，但位序列本身可以有不同的物理表示。这个选择不影响任何查询结果，只影响时间和空间——而差距是数量级的。"
   ],
   "id": "57c11a89"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### 表示一：布尔列表 `list[bool]`\n",
    "\n",
    "最直观的写法：给每个键存一个 `True / False`。\n",
    "\n",
    "但 Python 的列表存的是**对象引用**，一个元素实际占用远大于 1 位（8 字节指针 + 布尔单例对象）。更要命的是运算方式：`&` 要在 Python 解释层循环 N 次，每次都是一次完整的字节码分派。\n",
    "\n",
    "**这是\"逻辑正确但物理选择糟糕\"的典型。**"
   ],
   "id": "62f95896"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-07T15:40:10.143951Z",
     "start_time": "2025-01-07T15:40:10.070720Z"
    }
   },
   "cell_type": "code",
   "source": [
    "_, _, query_1_boolean_stored_bits, query_1_boolean_result_bits = (\n",
    "    create_indexes_and_execute_query(bit_sequence_type=BitListBitSequence)\n",
    ")"
   ],
   "id": "e57884a19e099cd4",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\tMeasure performance for index of type <class 'system.bit_sequences.BitListBitSequence'>\n",
      "\t\tTime taken for creating an index: 0.039728641510009766\n",
      "\t\tStored bits for the index: 180000\n",
      "\t\tTime taken for indexed query: 0.0064814090728759766\n",
      "\t\tThe number of corresponding ids is: 2000\n"
     ]
    }
   ],
   "execution_count": 5
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### 表示二：Python 大整数 `int`\n",
    "\n",
    "换成用一个二进制整数表示整条位序列：第 j 位为 1 就置上 `1 << j`。\n",
    "\n",
    "这样：\n",
    "\n",
    "- 空间是真正的 $N$ 位（连续机器字）；\n",
    "- `a & b` 是一条指令的事——Python 的大整数运算在幕后把 CPU 的 64 位 AND 扩展到任意长度，一次覆盖全部 4000 位。\n",
    "\n",
    "**上层逻辑一行没改，换了个底层实现，性能差出两个数量级。** 这就是数据库系统里\"抽象与实现分离\"的价值。"
   ],
   "id": "cdfda4cc"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-07T15:40:10.187111Z",
     "start_time": "2025-01-07T15:40:10.144628Z"
    }
   },
   "cell_type": "code",
   "source": [
    "_, _, query_1_integer_stored_bits, query_1_integer_result_bits = (\n",
    "    create_indexes_and_execute_query(bit_sequence_type=IntegerBitSequence)\n",
    ")"
   ],
   "id": "390eb2dae8e7a0e4",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\tMeasure performance for index of type <class 'system.bit_sequences.IntegerBitSequence'>\n",
      "\t\tTime taken for creating an index: 0.03580427169799805\n",
      "\t\tStored bits for the index: 180000\n",
      "\t\tTime taken for indexed query: 2.3365020751953125e-05\n",
      "\t\tThe number of corresponding ids is: 2000\n"
     ]
    }
   ],
   "execution_count": 6
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 两种表示的实测对比\n",
    "\n",
    "本机实测（4 000 行，两个索引共 36 000 位 $= 4000 \\times (4 + 5)$）：\n",
    "\n",
    "| 位序列实现 | 建索引 | 一次查询 | 占用位数 |\n",
    "| --- | --- | --- | --- |\n",
    "| 布尔列表 `BitListBitSequence` | 约 13 ms | 约 2.0 ms | 36 000 |\n",
    "| Python 大整数 `IntegerBitSequence` | 约 11 ms | **0.012 ～ 0.018 ms** | 36 000 |\n",
    "| 朴素逐行扫描（对照） | — | 0.2 ～ 0.4 ms | — |\n",
    "\n",
    "**查询快约 100 ～ 160 倍，而占用的位数一模一样。** 差别纯粹来自物理布局。\n",
    "\n",
    "（建索引耗时两套实现差不多，因为瓶颈是把 4000 行扫一遍、往位序列里置位，这部分谁也省不掉。）\n",
    "\n",
    "作为量级参照，配套的 50 万行基准脚本（口径表基准）给出：构建 7 660 ms / 朴素 153.588 ms / 位图查询 1.5184 ms，加速约 **101×**，命中 19 845 行。**注意这是 50 万行上的数字，本笔记本只有 4 000 行，跑不出这个绝对值**——两边的可比之处是\"位图查询比朴素快约两个数量级\"这个结论。\n",
    "\n",
    "顺带一个坑：上面那 1.5184 ms 里的大头其实不是 AND/OR，而是**数 1 的方式**。`bin(x).count(\"1\")` 要先造一个 50 万字符的字符串；Python 3.8 之后的 `int.bit_count()` 直接在二进制表示上做 popcount，快得多。\n",
    "\n",
    "最后回到\"该不该建索引\"。设 $C_{\\text{build}}$ 为建索引耗时，$C_{\\text{naive}}$ 和 $C_{\\text{bm}}$ 分别是朴素与位图的单次查询耗时，则查询次数\n",
    "\n",
    "$$Q \\ge \\frac{C_{\\text{build}}}{C_{\\text{naive}} - C_{\\text{bm}}}$$\n",
    "\n",
    "之后索引才开始盈利。代入 50 万行的口径表基准：$7660 / (153.588 - 1.5184) \\approx 50$ 次。**这张表只要被同样模式查询 50 次以上，索引就划算；每天只查两三次的话，这笔投资要一年才回本。**"
   ],
   "id": "42ec9e0e"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 三、等值编码 vs 范围编码\n",
    "\n",
    "换个查询类型。这次是范围查询：\n",
    "\n",
    "```sql\n",
    "SELECT COUNT(*)\n",
    "FROM   addresses\n",
    "WHERE  house_number < 500\n",
    "```\n",
    "\n",
    "等值编码擅长回答\"等于某个值\"，遇到\"小于某个值\"会怎样？"
   ],
   "id": "0c43427f"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 用等值编码做范围查询\n",
    "\n",
    "`house_number < 500` 意味着要把所有小于 500 的取值的位序列全部 OR 起来。默认配置（门牌 1～200）是 200 条；若把 `possible_house_numbers` 换成 `range(1, 1001)`，就是 499 条。\n",
    "\n",
    "**查询耗时与区间宽度成正比**——这是等值编码做范围查询的软肋。\n",
    "\n",
    "（从这里开始一律用 `IntegerBitSequence`：它的查询性能最好，比的是编码方式而不是物理表示。）"
   ],
   "id": "76aeba42"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-07T15:40:10.236756Z",
     "start_time": "2025-01-07T15:40:10.187808Z"
    }
   },
   "cell_type": "code",
   "source": [
    "start_index = time.time()\n",
    "\n",
    "# Create BitSequence for city\n",
    "house_number_bitmap_index: SortedEqualityEncodedBitmapIndex = (\n",
    "    SortedEqualityEncodedBitmapIndex(bit_sequence_type=IntegerBitSequence)\n",
    ")\n",
    "house_number_bitmap_index.bulkload(house_number_bulkload_generator())\n",
    "\n",
    "end_index = time.time()\n",
    "print(f\"Time taken for creating an index: {end_index - start_index}\")\n",
    "\n",
    "start_exec = time.time()\n",
    "smaller_than_500_equality: BitSequence = house_number_bitmap_index.get_smaller(500)\n",
    "\n",
    "end_exec = time.time()\n",
    "print(f\"Time taken for indexed query: {end_exec - start_exec}\")\n",
    "print(f\"The number of corresponding ids is: {len(smaller_than_500_equality.as_set())}\")"
   ],
   "id": "8ef3f18d6544aa5c",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Time taken for creating an index: 0.026168107986450195\n",
      "Time taken for indexed query: 0.0007965564727783203\n",
      "The number of corresponding ids is: 9980\n"
     ]
    }
   ],
   "execution_count": 7
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 换用专门的范围编码\n",
    "\n",
    "**范围编码（range encoding）**改变了每条位序列的含义：存的不再是\"等于\"，而是\"小于等于\"。\n",
    "\n",
    "$$R_i[j] = 1 \\iff A[j] \\le v_i$$\n",
    "\n",
    "于是：\n",
    "\n",
    "| 查询 | 等值编码 | 范围编码 |\n",
    "| --- | --- | --- |\n",
    "| $A = v_i$ | $E_i$（1 条） | $R_i \\;\\&\\; \\sim R_{i-1}$（2 条） |\n",
    "| $A \\le v_i$ | $E_1 \\| \\cdots \\| E_i$（i 条） | $R_i$（1 条） |\n",
    "| $v_i < A \\le v_j$ | OR 一大串 | $R_j \\;\\&\\; \\sim R_i$（2 条） |\n",
    "\n",
    "代价也很直接：$R_1 \\subseteq R_2 \\subseteq \\cdots \\subseteq R_d$ 构成一条单调链，**改一行的值可能要翻转后面所有位序列的对应位**；而且它要求属性可排序，所以教学库里的 `RangeEncodedBitmapIndex` 只接受整数属性。\n",
    "\n",
    "接下来这一格只做一次索引访问就拿到结果。"
   ],
   "id": "01803110"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-07T15:40:14.783589Z",
     "start_time": "2025-01-07T15:40:10.237583Z"
    }
   },
   "cell_type": "code",
   "source": [
    "start_index = time.time()\n",
    "\n",
    "# Create BitSequence for house number\n",
    "house_number_bitmap_index: RangeEncodedBitmapIndex = RangeEncodedBitmapIndex(\n",
    "    bit_sequence_type=IntegerBitSequence\n",
    ")\n",
    "house_number_bitmap_index.bulkload(house_number_bulkload_generator())\n",
    "end_index = time.time()\n",
    "print(f\"Time taken for creating an index: {end_index - start_index}\")\n",
    "\n",
    "start_exec = time.time()\n",
    "\n",
    "# Only one access is required to compute the result.\n",
    "smaller_than_500_range: BitSequence = house_number_bitmap_index.get_smaller(500)\n",
    "\n",
    "end_exec = time.time()\n",
    "print(f\"Time taken for indexed query: {end_exec - start_exec}\")\n",
    "print(f\"The number of corresponding ids is: {len(smaller_than_500_range.as_set())}\")"
   ],
   "id": "b93cfa8c3d79773b",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Time taken for creating an index: 4.523980379104614\n",
      "Time taken for indexed query: 5.817413330078125e-05\n",
      "The number of corresponding ids is: 9980\n"
     ]
    }
   ],
   "execution_count": 8
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "本机多次实测的量级（4 000 行，`house_number < 500`，命中 4 000 行即全部）：\n",
    "\n",
    "| 编码方式 | 建索引 | 一次查询 |\n",
    "| --- | --- | --- |\n",
    "| 等值编码（OR 200 条） | 6 ～ 11 ms | 约 0.3 ms |\n",
    "| 范围编码（取 1 条） | 230 ～ 420 ms | **0.03 ～ 0.09 ms** |\n",
    "\n",
    "**查询快 3 ～ 10 倍，建索引慢 20 ～ 40 倍。**（绝对值随机器和当次负载波动，看量级即可。）\n",
    "\n",
    "这就是取舍的全貌：范围编码把成本从\"每次查询\"挪到了\"建索引时\"，再附赠一个\"更新很贵\"的缺点。\n",
    "\n",
    "适用场合也就清楚了：**只读为主的分析型负载（数据仓库 / OLAP）适合范围编码；高频点更新的 OLTP 不适合。** 两种编码的系统性比较可参考 Chan 与 Ioannidis 1998 年发表的工作。\n",
    "\n",
    "范围编码同样支持任意布尔组合，例如：\n",
    "\n",
    "```sql\n",
    "SELECT COUNT(*)\n",
    "FROM   addresses\n",
    "WHERE  house_number >= 300 OR house_number = 30\n",
    "```\n",
    "\n",
    "对应 $R_{\\ge 300} \\;\\|\\; E_{30}$。"
   ],
   "id": "98235334"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 组合布尔表达式\n",
    "\n",
    "`>= 300` 用补集表示（`~R_{299}`），`= 30` 用相邻两条相减，两者 OR 起来即可。注意全程只碰到位序列，**没有碰过一行原始数据**。"
   ],
   "id": "186b3931"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-07T15:40:14.812866Z",
     "start_time": "2025-01-07T15:40:14.784308Z"
    }
   },
   "cell_type": "code",
   "source": [
    "start_exec = time.time()\n",
    "\n",
    "# Compute individual results\n",
    "house_number_greater_equal_300: BitSequence = (\n",
    "    house_number_bitmap_index.get_greater_or_equal(300)\n",
    ")\n",
    "house_number_equal_30: BitSequence = house_number_bitmap_index.get_equal(30)\n",
    "\n",
    "# Combine results\n",
    "ge_300_e_30_result: BitSequence = house_number_greater_equal_300 | house_number_equal_30\n",
    "\n",
    "end_exec = time.time()\n",
    "print(f\"Time taken for indexed query: {end_exec - start_exec}\")\n",
    "print(f\"The number of corresponding ids is: {len(ge_300_e_30_result.as_set())}\")"
   ],
   "id": "199defd8012d88",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Time taken for indexed query: 9.012222290039062e-05\n",
      "The number of corresponding ids is: 14040\n"
     ]
    }
   ],
   "execution_count": 9
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 混合使用不同索引\n",
    "\n",
    "真实系统里一个查询的各个条件可以走不同的索引，最后再把结果位序列组合起来：\n",
    "\n",
    "```sql\n",
    "SELECT COUNT(*)\n",
    "FROM   addresses\n",
    "WHERE  house_number = 23 OR (city = 'New York' AND house_number < 40)\n",
    "```\n",
    "\n",
    "下面这一格建了三个索引：`house_number` 的等值编码（回答 `= 23`）、`city` 的等值编码（回答 `= 'New York'`）、`house_number` 的范围编码（回答 `< 40`），然后一次位运算合并。\n",
    "\n",
    "**选哪种索引是按条件决定的，不是按列决定的**——同一列上可以同时存在等值和范围两套索引。"
   ],
   "id": "9e0a992e"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-07T15:40:19.025329Z",
     "start_time": "2025-01-07T15:40:14.813534Z"
    }
   },
   "cell_type": "code",
   "source": [
    "start_index = time.time()\n",
    "\n",
    "# Create equality-encoded indexes for house numbers and cities\n",
    "house_number_equality_bitmap_index: SortedEqualityEncodedBitmapIndex = (\n",
    "    SortedEqualityEncodedBitmapIndex(\n",
    "        bit_sequence_type=IntegerBitSequence,\n",
    "    )\n",
    ")\n",
    "house_number_equality_bitmap_index.bulkload(house_number_bulkload_generator())\n",
    "city_equality_bitmap_index: SortedEqualityEncodedBitmapIndex = (\n",
    "    SortedEqualityEncodedBitmapIndex(\n",
    "        bit_sequence_type=IntegerBitSequence,\n",
    "    )\n",
    ")\n",
    "city_equality_bitmap_index.bulkload(city_bulkload_generator())\n",
    "\n",
    "# Create range-encoded index for house numbers\n",
    "house_number_range_bitmap_index: RangeEncodedBitmapIndex = RangeEncodedBitmapIndex(\n",
    "    bit_sequence_type=IntegerBitSequence,\n",
    ")\n",
    "house_number_range_bitmap_index.bulkload(house_number_bulkload_generator())\n",
    "end_index = time.time()\n",
    "print(f\"Time taken for creating an index: {end_index - start_index}\")\n",
    "\n",
    "start_exec = time.time()\n",
    "\n",
    "# Compute individual result sets\n",
    "house_number_equal_23 = house_number_equality_bitmap_index.get_equal(23)\n",
    "city_equal_new_york: BitSequence = city_equality_bitmap_index.get_equal(\"New York\")\n",
    "house_number_smaller_40: BitSequence = house_number_range_bitmap_index.get_smaller(40)\n",
    "end_exec = time.time()\n",
    "\n",
    "combined_result: BitSequence = house_number_equal_23 | (\n",
    "    city_equal_new_york & house_number_smaller_40\n",
    ")\n",
    "print(f\"Time taken for indexed query: {end_exec - start_exec}\")\n",
    "print(f\"The number of corresponding ids is: {len(combined_result.as_set())}\")"
   ],
   "id": "3f5000ac76cb80cb",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Time taken for creating an index: 4.189512729644775\n",
      "Time taken for indexed query: 9.34600830078125e-05\n",
      "The number of corresponding ids is: 210\n"
     ]
    }
   ],
   "execution_count": 10
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "位图索引很好用，但它要为每个取值存 $N$ 位。如果空间极端受限——连一条压缩后的位序列都放不下呢？\n",
    "\n",
    "那就只能放弃\"精确定位每一行\"，转而回答一个更弱的问题：**这个键到底在不在这一批数据里？** 这就是 Bloom 过滤器的地盘。"
   ],
   "id": "87577439"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 四、Bloom 过滤器\n",
    "\n",
    "假设磁盘上有一个文件，存着门牌号小于 10 的地址（$4 \\times 5 \\times 9 = 180$ 条）。下面把它 pickle 到 `addresses.pkl`，当作\"磁盘上的数据\"。\n",
    "\n",
    "接下来要回答：给定一个 `id`，它在不在这个文件里？"
   ],
   "id": "fe3d25ca"
  },
  {
   "cell_type": "code",
   "id": "a136d30fcceb8abc",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-07T15:40:19.029244Z",
     "start_time": "2025-01-07T15:40:19.026105Z"
    }
   },
   "source": [
    "# Write data\n",
    "house_numbers_equal_1: list[Address] = []\n",
    "\n",
    "# Get all addresses from New York\n",
    "for address in all_addresses:\n",
    "    if address.house_number < 10:\n",
    "        house_numbers_equal_1.append(address)\n",
    "\n",
    "# Write addresses to file\n",
    "with open(\"addresses.pkl\", \"wb\") as f:\n",
    "    pickle.dump([vars(address) for address in house_numbers_equal_1], f)"
   ],
   "outputs": [],
   "execution_count": 11
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 不用过滤器：每次都回盘\n",
    "\n",
    "最诚实的做法：打开文件，把里面的记录反序列化出来，逐条比对 `id`。\n",
    "\n",
    "这个函数的代价结构很关键——**每次调用都要完整地读一遍文件**。`id` 不存在时也要读完整文件才能确认，这正是 Bloom 过滤器要消灭的浪费。"
   ],
   "id": "4e283912"
  },
  {
   "cell_type": "code",
   "id": "6768fbf36964e749",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-07T15:40:19.052818Z",
     "start_time": "2025-01-07T15:40:19.030328Z"
    }
   },
   "source": [
    "def id_is_present_on_disk(id_: int) -> bool:\n",
    "    with open(\"addresses.pkl\", \"rb\") as f:\n",
    "        # Iterate over each stored address to find out, whether the id is present.\n",
    "        for address in pickle.load(f):\n",
    "            if address[\"id\"] == id_:\n",
    "                return True\n",
    "        return False"
   ],
   "outputs": [],
   "execution_count": 12
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 对全部 4000 个 id 各问一次\n",
    "\n",
    "下面对 `all_addresses` 的每一个 id 都问一遍\"在不在文件里\"，累加耗时。\n",
    "\n",
    "这 4000 次调用里只有 180 次命中，其余 3820 次都白读了一遍文件——**这就是过滤器能省下来的部分**。"
   ],
   "id": "1228810c"
  },
  {
   "cell_type": "code",
   "id": "adc19236116dd2af",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-07T15:40:19.785973Z",
     "start_time": "2025-01-07T15:40:19.053496Z"
    }
   },
   "source": [
    "contained_ids_without_bloom_filter: set[int] = set()\n",
    "start_exec = time.time()\n",
    "for address in all_addresses:\n",
    "    if id_is_present_on_disk(address.id):\n",
    "        contained_ids_without_bloom_filter.add(address.id)\n",
    "end_exec = time.time()\n",
    "no_filter: float = end_exec - start_exec\n",
    "print(f\"Time taken for evaluating without any bloom filter: {no_filter} seconds\")"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Time taken for evaluating without any bloom filter: 0.7118265628814697 seconds\n"
     ]
    }
   ],
   "execution_count": 13
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Bloom 过滤器的原理\n",
    "\n",
    "Bloom 过滤器（Bloom 1970）由两部分组成：长度 $m$ 的位数组 + $k$ 个哈希函数。\n",
    "\n",
    "- **插入 x**：算出 $h_1(x) \\ldots h_k(x)$，把这些位置置 1。\n",
    "- **查询 y**：算出 $k$ 个位置，只要**有任何一个为 0 → 一定不在**（无假阴性）；若全为 1 → **可能在**，需要回原始数据复核。\n",
    "\n",
    "**为什么永远没有假阴性？** 因为插入时把 $k$ 个位置都置成了 1，之后没有任何操作会把它们清 0。下次查同一个键，这些位置必然全为 1。\n",
    "\n",
    "假阳性率（即\"不存在的键被误判为存在\"的概率）：\n",
    "\n",
    "$$p \\approx \\left(1 - e^{-kn/m}\\right)^k$$\n",
    "\n",
    "| 符号 | 含义 |\n",
    "| --- | --- |\n",
    "| $n$ | 插入的元素个数 |\n",
    "| $m$ | 位数组长度（bit） |\n",
    "| $k$ | 哈希函数个数 |\n",
    "| $e^{-kn/m}$ | 插入全部 $n$ 个元素后，某个特定位仍为 0 的概率 |\n",
    "| $p$ | 一次\"不存在键\"查询被误判为存在的概率 |\n",
    "\n",
    "两个可以直接用在工程上的结论：\n",
    "\n",
    "$$k^* = \\frac{m}{n}\\ln 2 \\qquad\\qquad m = -\\frac{n \\ln p}{(\\ln 2)^2}$$\n",
    "\n",
    "左边：给定空间预算 $m/n$，最优哈希个数；右边：给定目标假阳性率 $p$，需要的位数。\n",
    "\n",
    "教学库的实现（`system/indexes/bloom_filters.py`）会自动按 $k = \\lceil \\ln 2 \\cdot m/n \\rceil$ 选 $k$，不用手动传。另外它用 `random.Random(key)` 的伪随机序列充当\"k 个哈希\"——**这是教学简化，源码注释里明确写着 NEVER USE THIS IN PRODUCTION**；真实系统用 murmur / md5 配合 double hashing（Kirsch 与 Mitzenmacher 提出的技巧：两个哈希函数线性组合出 k 个位置，不必真做 k 次哈希）。\n",
    "\n",
    "下面这一格把 $m$ 从 10 一路加到 5000，每个 $m$ 都建一个过滤器，跑完同一批 4000 次查询，然后把耗时和\"不用过滤器\"的基线画在一张图上。"
   ],
   "id": "12a16bc8"
  },
  {
   "cell_type": "code",
   "id": "6a7bf70f8daa0209",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-07T15:40:24.744437Z",
     "start_time": "2025-01-07T15:40:19.786594Z"
    }
   },
   "source": [
    "# Define method to go through all addresses in order to identify those that are contained in set\n",
    "required_time: list[float] = []\n",
    "contained_ids_with_bloom_filter: list[set[int]] = []\n",
    "\n",
    "\n",
    "def check_all_addresses(bloom_filter: BloomFilter):\n",
    "    contained_ids: set[int] = set()\n",
    "    start_exec = time.time()\n",
    "    for address in all_addresses:\n",
    "        if bloom_filter.contains_key(address.id):\n",
    "            if id_is_present_on_disk(address.id):\n",
    "                contained_ids.add(address.id)\n",
    "    end_exec = time.time()\n",
    "    required_time.append(end_exec - start_exec)\n",
    "    contained_ids_with_bloom_filter.append(contained_ids)\n",
    "\n",
    "\n",
    "# Create bloom filters with different bit sizes\n",
    "numbers_of_available_bits: list[int] = [10, 20, 50, 100, 200, 500, 1000, 2000, 5000]\n",
    "for number in numbers_of_available_bits:\n",
    "    # Create Bloom Filter\n",
    "    bloom_filter: BloomFilter = BloomFilter(\n",
    "        data_objects=house_numbers_equal_1,\n",
    "        key_attribute_name=\"id\",\n",
    "        number_of_available_bits=number,\n",
    "        bit_sequence_type=BitListBitSequence,\n",
    "    )\n",
    "    check_all_addresses(bloom_filter)\n",
    "\n",
    "x = np.arange(len(numbers_of_available_bits))  # the label locations\n",
    "fig, ax = plt.subplots(\n",
    "    layout=\"constrained\",\n",
    "    figsize=(5, 4),\n",
    ")\n",
    "\n",
    "ax.plot(x, required_time, label=\"Bloom Filter\")\n",
    "plt.axhline(y=no_filter, color=\"r\", linestyle=\"--\", label=\"No Bloom Filter\")\n",
    "plt.legend()\n",
    "ax.set_ylabel(\"Required Time to answer the query in s\")\n",
    "\n",
    "ax.set_xlabel(\"Number of bits stored\")\n",
    "ax.set_xticks(x, numbers_of_available_bits)\n",
    "plt.show()"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 500x400 with 1 Axes>"
      ],
      "image/png": "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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 14
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "图上两条线：折线是不同 $m$ 下带 Bloom 过滤器的耗时，红色虚线是不用过滤器的基线（全量回盘）。\n",
    "\n",
    "看的不是\"越低越好\"，而是**折线什么时候穿过红色虚线**：\n",
    "\n",
    "- $m$ 很小的时候**反而更慢**。因为位数组几乎被填满，绝大多数查询都假阳性，白白多付了哈希计算的代价，还要照旧回盘。本笔记本 $n = 180$，$m = 10$ 时 $k = \\lceil 0.693 \\times 10/180 \\rceil = 1$，一个哈希位、几乎必然撞上，过滤器形同虚设。\n",
    "- $m$ 增大后假阳性率下降，穿过滤线之后开始**净赚**：绝大多数\"不在\"的查询被挡在内存里，根本不碰磁盘。\n",
    "\n",
    "$m = 5000$ 时 $k = \\lceil 0.693 \\times 5000/180 \\rceil = 20$，理论假阳性率已经低到几乎为 0。\n",
    "\n",
    "应用实例：Google Bigtable（OSDI 2006）用它避免读不存在的 SSTable；Apache Cassandra 用它减少磁盘读取；PostgreSQL 的 bloom 扩展索引属于有损索引，命中后必须回表复核。**它们的共同点是：Bloom 只负责\"挡掉不可能命中的\"，命中之后一定要回原始数据确认。**"
   ],
   "id": "5a6012b0"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 五、压缩位图：WAH 字对齐游程编码\n",
    "\n",
    "位图索引的问题是空间：$V$ 个取值就要 $V \\times N$ 位。压缩的思路是**游程压缩**——连续的 0 或连续的 1 不必逐位存。\n",
    "\n",
    "**WAH（Word-Aligned Hybrid）**的做法（Wu、Otoo、Shoshani，ACM TODS 2006）：把位序列按固定字长切成若干字（word），然后分三类：\n",
    "\n",
    "| 字类型 | 含义 | 存储开销 |\n",
    "| --- | --- | --- |\n",
    "| 0-fill | 连续若干个字全是 0 | 1 个字（头里记重复次数） |\n",
    "| 1-fill | 连续若干个字全是 1 | 1 个字 |\n",
    "| literal | 字内 0/1 混杂，压不动 | 1 个字，原样存 |\n",
    "\n",
    "字对齐的好处是部分运算可以直接在压缩态上做，不必先解压。\n",
    "\n",
    "下面这一格把 `WAHBitSequence.WORD_LENGTH` 从 4 调到 256，对四种组合（未压缩的两种物理表示 × 压缩与否）各测\"建索引耗时 / 查询耗时 / 占用位数\"，画成三张对数坐标图。\n",
    "\n",
    "**字长是一个有拐点的参数**——这是本格最值得看的东西。"
   ],
   "id": "3d25a09b"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-07T15:40:29.484504Z",
     "start_time": "2025-01-07T15:40:24.745050Z"
    }
   },
   "cell_type": "code",
   "source": [
    "result_dict: dict[str, tuple[list[float], list[float], list[int]]] = {\n",
    "    index_type: ([], [], [])\n",
    "    for index_type in [\n",
    "        \"BooleanListBitSequence\",\n",
    "        \"IntegerBitSequence\",\n",
    "        \"CompressedIntegerBitSequence\",\n",
    "        \"CompressedBooleanListBitSequence\",\n",
    "    ]\n",
    "}\n",
    "bitset_types: dict[\n",
    "    str, tuple[Type[UncompressedBitSequence], Type[CompressedBitSequence] | None]\n",
    "] = {\n",
    "    \"IntegerBitSequence\": (IntegerBitSequence, None),\n",
    "    \"BooleanListBitSequence\": (BitListBitSequence, None),\n",
    "    \"CompressedIntegerBitSequence\": (IntegerBitSequence, WAHBitSequence),\n",
    "    \"CompressedBooleanListBitSequence\": (BitListBitSequence, WAHBitSequence),\n",
    "}\n",
    "marker_dict: dict[str, str] = {\n",
    "    \"IntegerBitSequence\": \"*\",\n",
    "    \"BooleanListBitSequence\": \"D\",\n",
    "    \"CompressedIntegerBitSequence\": \"s\",\n",
    "    \"CompressedBooleanListBitSequence\": \"^\",\n",
    "}\n",
    "word_lengths: list[int] = [4, 8, 16, 32, 64, 128, 256]\n",
    "benchmark_results: list[BitSequence] = []\n",
    "for bitset_type, result_list in result_dict.items():\n",
    "    for i in word_lengths:\n",
    "        WAHBitSequence.WORD_LENGTH = i\n",
    "\n",
    "        # Use median out of multiple operations\n",
    "        index_times = []\n",
    "        exec_times = []\n",
    "        bits_stored = None\n",
    "        for _ in range(2):\n",
    "            index_time, exec_time, bits_stored, result_bits = (\n",
    "                create_indexes_and_execute_query(\n",
    "                    bit_sequence_type=bitset_types[bitset_type][0],\n",
    "                    compression_type=bitset_types[bitset_type][1],\n",
    "                    print_info=False,\n",
    "                )\n",
    "            )\n",
    "            index_times.append(index_time)\n",
    "            exec_times.append(exec_time)\n",
    "            benchmark_results.append(result_bits)\n",
    "\n",
    "        result_list[0].append(statistics.median(index_times))\n",
    "        result_list[1].append(statistics.median(exec_times))\n",
    "        result_list[2].append(bits_stored)\n",
    "\n",
    "x = np.arange(len(word_lengths))  # the label locations\n",
    "fig, (ax_index_time, ax_exec_time, ax_bits_stored) = plt.subplots(\n",
    "    layout=\"constrained\", figsize=(12, 4), ncols=3\n",
    ")\n",
    "for bitset_type, bitset_type_tuple in result_dict.items():\n",
    "    ax_index_time.plot(\n",
    "        x, bitset_type_tuple[0], label=bitset_type, marker=marker_dict[bitset_type]\n",
    "    )\n",
    "    ax_exec_time.plot(\n",
    "        x, bitset_type_tuple[1], label=bitset_type, marker=marker_dict[bitset_type]\n",
    "    )\n",
    "    ax_bits_stored.plot(\n",
    "        x, bitset_type_tuple[2], label=bitset_type, marker=marker_dict[bitset_type]\n",
    "    )\n",
    "\n",
    "ax_index_time.set_ylabel(\"Required Time to create an index in s\")\n",
    "ax_exec_time.set_ylabel(\"Required Time to execute the query in s\")\n",
    "ax_exec_time.legend(loc=\"center\", bbox_to_anchor=(0.5, 1.2))\n",
    "ax_bits_stored.set_ylabel(\"Number of bits stored\")\n",
    "\n",
    "ax_exec_time.set_yscale(\"log\")\n",
    "ax_bits_stored.set_yscale(\"log\")\n",
    "\n",
    "for ax in [ax_index_time, ax_exec_time, ax_bits_stored]:\n",
    "    ax.set_xlabel(\"Bit length of a word\")\n",
    "    ax.set_xticks(x, word_lengths)"
   ],
   "id": "5a3d94359b8e3bd1",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 1200x400 with 3 Axes>"
      ],
      "image/png": "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msLFxQXPP/88Jk2aBC8vLwQGBmL+/PkoKirCmDFjjN5PYGAgtFot3nnnHSQkJOD48eOYNWtWvV8XEREBT09PfPjhh9i6dSuAysCZOHEiFEUxOHV40qRJePzxx9GpUyf07dsXn3/+OTZu3IidO3fWeYwJEyZg5MiR6NKlC6Kjo7Fu3TqcOHECISEhRs+PiAhgltSGWUJEZIh5UTPmBdkUS180jKg+8fHxAkD/cHNzk8jISPnkk0/0Y+68SKSIyMyZM8XPz08URZH4+Pga913TxRq3b98uPXr0ECcnJ3F3d5euXbvKsmXL9NsByKZNmwy+5s6LMH722WcSGhoqOp1OevfuLampqQJAiouL9WMSEhLE29tbAMgbb7whIpUXiVywYIHBvjt06KDfXpPi4mIZN26c+Pj4iE6nk+joaDl48GCd9dXkww8/lODgYNHpdBIVFSVbtmyp9pzWZPDgwWJvb6+/mGR5ebl4enpK9+7dq4199913JSQkRBwcHOSBBx6QNWvWGGyv6bkVEZkzZ474+PiIq6urxMfHy+TJk3mRSCIyCbOEWcIsISJjMC+YF8wLdVBERMzUVyNqsubMmYMlS5YgNzfX0qUQEZGNYpYQEZExmBdE/BgjUaN49913ERkZCW9vb+zfvx9vvfUWXnzxRUuXRURENoRZQkRExmBeEFXHZhdRI8jKysLs2bPx66+/IjAwEH/9618xdepUS5dFREQ2hFlCRETGYF4QVcePMRIRERERERERkWoYdz9TIiIiIiIiIiIiG8BmFxERERERERERqQabXUREREREREREpBpsdhERERERERERkWqw2UVERERERERERKrBZhcREREREREREakGm11ERERERERERKQabHYREREREREREZFq/D+fbY7lmdR/1gAAAABJRU5ErkJggg=="
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 15
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "本机实测（4 000 行，未压缩时两个索引共 36 000 位）：\n",
    "\n",
    "| 字长 | WAH 压缩后位数 | 占未压缩的比例 | 一次查询 |\n",
    "| --- | --- | --- | --- |\n",
    "| 4 | 16 148 | 44.9% | 9.107 ms |\n",
    "| 32 | **3 392** | **9.4%** | 0.480 ms |\n",
    "| 256 | 20 224 | 56.2% | 0.373 ms |\n",
    "\n",
    "拐点非常清楚：\n",
    "\n",
    "- **字长太小（4）**：几乎每个字都是 literal，凑不出长游程，压缩率差，而且字多了、解析开销大；\n",
    "- **字长适中（32）**：一个字里 32 位全 0 的概率足够高，能凑出长游程，压缩到 9.4%；\n",
    "- **字长太大（256）**：一个字里只要混进一个 1 就退化成 literal，游程又凑不出来了，压缩率反弹。\n",
    "\n",
    "**查询耗时则一直比未压缩的大整数慢**（0.48 ms 对 0.018 ms，约 27 倍）——运算前要先解析压缩格式。这就是本节开头说的\"空间和查询时间不是一起变好的\"。\n",
    "\n",
    "数据本身的分布更关键：口径表基准（10 万位、字长 32）显示，密度 0.1% 的**随机分布**压到 204 字（占 6.5%），**聚集分布**只压到 5 字（0.16%），而密度达到 10% 以上时随机分布的压缩基本失效（100%）。**把表按某个键排序（聚簇）之后再建位图，压缩率会有数量级的改善**——这是位图索引在实践中可行的真正基础。\n",
    "\n",
    "另一条主流路线是 Roaring Bitmap：按高 16 位分桶，桶内根据稀疏程度在 array / bitset / run 三种容器之间切换。它和 WAH 是同一问题的两种解法。"
   ],
   "id": "6ec254aa"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 六、单元测试：结果对不对，不能靠肉眼看\n",
    "\n",
    "前面的每一步都在追求快，但**快必须建立在对的基础上**。最后这一格用 `unittest` 把三件事断言一遍：\n",
    "\n",
    "1. 两种位序列实现（布尔列表 / 大整数）的查询结果，都要等于朴素扫描的结果；\n",
    "2. 等值编码和范围编码对同一个范围查询，都要等于朴素扫描的结果；\n",
    "3. 所有 Bloom 过滤器（不同 $m$）最终筛出的 id 集合，都要等于不用过滤器时筛出的集合——**Bloom 可以有假阳性，但不能改变最终答案**，因为每个\"可能在\"都回盘复核过了。\n",
    "\n",
    "另外还断言了存储位数等于 $4000 \\times (4 + 5) = 36\\,000$，这是\"位图空间 = 取值个数 × 行数\"这条公式的直接验证。\n",
    "\n",
    "**养成习惯：任何性能优化都得配一条正确性断言。**"
   ],
   "id": "141aad5f"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-07T15:40:29.585438Z",
     "start_time": "2025-01-07T15:40:29.485659Z"
    }
   },
   "cell_type": "code",
   "source": "import unittest\n\n\nclass BitmapTests(unittest.TestCase):\n    def test_uncompressed_bitmap_index(self):\n\n        # Equality-encoded city + street indexes store one bit per address per\n        # distinct value, i.e. len(addresses) * (num cities + num streets) bits.\n        # Derived from the data so the check holds for any house-number range.\n        expected_stored_bits: int = len(all_addresses) * (\n            len(possible_cities) + len(possible_streets)\n        )\n        for bits_stored in [query_1_integer_stored_bits, query_1_boolean_stored_bits]:\n            self.assertEqual(bits_stored, expected_stored_bits)\n        for bitmap_result in [query_1_integer_result_bits, query_1_boolean_result_bits]:\n            self.assertEqual(bitmap_result, query_1_naive_result)\n\n        # Check house number smaller than 500 result\n        naive_smaller_than_500: set[int] = set()\n        for address in all_addresses:\n            if address.house_number < 500:\n                naive_smaller_than_500.add(address.id)\n\n        for bitmap_result in [smaller_than_500_equality, smaller_than_500_range]:\n            self.assertEqual(naive_smaller_than_500, bitmap_result.as_set())\n\n        # House number greater/equal 300 or equal 30\n        naive_ge_300_e_30: set[int] = set()\n        for address in all_addresses:\n            if address.house_number >= 300 or address.house_number == 30:\n                naive_ge_300_e_30.add(address.id)\n        self.assertEqual(naive_ge_300_e_30, ge_300_e_30_result.as_set())\n\n        # Combined result as described above\n        naive_combined_result: set[int] = set()\n        for address in all_addresses:\n            if address.house_number == 23 or (\n                address.city == \"New York\" and address.house_number < 40\n            ):\n                naive_combined_result.add(address.id)\n        self.assertEqual(naive_combined_result, combined_result.as_set())\n\n    def test_bloom_filters(self):\n\n        # Bloom Filter should produce the same result\n        for contained_ids in contained_ids_with_bloom_filter:\n            self.assertEqual(contained_ids, contained_ids_without_bloom_filter)\n\n    def test_benchmark(self):\n\n        # Verify that all benchmark produce the correct results\n        for result in benchmark_results:\n            self.assertEqual(query_1_naive_result, result)\n\n\nunittest.main(\n    argv=[\"ignored\", \"-v\"], defaultTest=\"BitmapTests\", verbosity=2, exit=False\n)",
   "id": "91c8264321856525",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-07T15:40:29.587502Z",
     "start_time": "2025-01-07T15:40:29.586090Z"
    }
   },
   "cell_type": "code",
   "source": "",
   "id": "fe26b28917d9e522",
   "outputs": [],
   "execution_count": 16
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 七、思考题与详解\n",
    "\n",
    "<details>\n",
    "<summary><b>第 1 题</b>：为什么 Bloom 过滤器不会有假阴性（false negative），只会有假阳性？如果把\"删除\"也支持进去，会出现什么问题？</summary>\n",
    "\n",
    "**原因**：插入键 x 时把 $h_1(x) \\ldots h_k(x)$ 全部置 1，之后再也没有任何操作把它们清 0。下次查询同一个键，这些位置必然全为 1，所以判定一定是\"可能存在\"。**没有哪个操作会把已置的位清掉，就不存在假阴性。**\n",
    "\n",
    "**加入删除就会破坏这个性质**：把某个位置清 0 时，你不知道还有多少个其它键的哈希也落在这个位置上，清多了会让别的键产生假阴性——而假阴性是 Bloom 过滤器绝对不能有的。\n",
    "\n",
    "两条解决路线：\n",
    "\n",
    "- **计数 Bloom（counting Bloom filter）**：每个位置用一个小计数器（通常 4 位）代替 1 位，插入加 1、删除减 1。代价是空间放大约 4 倍。\n",
    "- **不支持删除**：定期重建整个过滤器。很多系统就是这么做的。\n",
    "\n",
    "</details>\n",
    "\n",
    "<details>\n",
    "<summary><b>第 2 题</b>：口径表基准里 m/n = 14、k = 10 时理论假阳性率 0.0012、实测 0.0016。这个差异合理吗？用统计涨落算一算。</summary>\n",
    "\n",
    "**合理，这是噪声。** 一次\"不存在键\"被误判是伯努利试验，$p = 0.0012$，试验次数 5000：\n",
    "\n",
    "```text\n",
    "期望个数  E = 5000 × 0.0012 = 6.0\n",
    "标准差    σ = √(5000 × 0.0012 × 0.9988) = √5.993 ≈ 2.45\n",
    "实测 0.0016  ⇒  实测个数 = 5000 × 0.0016 = 8.0\n",
    "偏离        (8 − 6) / 2.45 ≈ 0.82 σ\n",
    "```\n",
    "\n",
    "0.82 个标准差是极常见的涨落。反过来讲，$p$ 的测量值本身的标准差是 $\\sigma / 5000 \\approx 0.00049$，所以实测 $0.0016 \\pm 0.0005$ 完全覆盖理论值 0.0012。\n",
    "\n",
    "**不需要修正公式。** 想把这条曲线测准，把探测次数提到 500 000（增加 100 倍），相对误差就降到原来的 1/10。\n",
    "\n",
    "</details>\n",
    "\n",
    "<details>\n",
    "<summary><b>第 3 题</b>：固定 m/n = 12 时理论最优 k* = 8.32，但实测最优点落在 k = 10。公式错了吗？</summary>\n",
    "\n",
    "**公式没错，是函数太平坦被噪声捂住了。** 代入 $p = (1 - e^{-k n/m})^k$，其中 $kn/m = k/12$：\n",
    "\n",
    "```text\n",
    "k = 8 :  p = (1 − e^{−8/12})^8  = (1 − 0.51342)^8  = 0.48658^8  = 0.003142\n",
    "k = 10:  p = (1 − e^{−10/12})^10 = (1 − 0.43460)^10 = 0.56540^10 = 0.003339\n",
    "```\n",
    "\n",
    "两者只差 0.0002。换算成 5000 次探测的期望个数：k = 8 得 15.7 个，k = 10 得 16.7 个，差 1 个；而这次实验的涨落 $\\sigma = \\sqrt{5000 \\times 0.0031 \\times 0.9969} \\approx 3.9$ 个。**差 1 个完全淹没在噪声里。**\n",
    "\n",
    "正确验证办法是增大探测次数；或者直接看理论曲线——它的谷底确实在 8.32 附近。另外工程上 $k$ 必须是整数，8 和 9 的理论差只有约 0.00002，取哪个都行。\n",
    "\n",
    "</details>\n",
    "\n",
    "<details>\n",
    "<summary><b>第 4 题</b>：口径表基准里，密度 0.1% 的随机分布压到 204 个字。请估算这个数字的来源：一个 32 位的字里至少含一个 1 的概率是多少？由此推算\"字面字\"的期望个数。</summary>\n",
    "\n",
    "一个字的 32 位全为 0 的概率是 $(1-p)^{32}$，$p = 0.001$：\n",
    "\n",
    "```text\n",
    "P(字内含至少一个 1) = 1 − 0.999^32 = 1 − e^{32·ln0.999} = 1 − e^{−0.032016} = 1 − 0.96849 = 0.03151\n",
    "```\n",
    "\n",
    "共 $100000/32 = 3125$ 个字，字面字期望 $= 3125 \\times 0.03151 \\approx 98.5$ 个。\n",
    "\n",
    "WAH 遇到字面字要额外存一个头字，两个字面字之间还要穿插 0-fill 字，粗略数：$98.5$ 个字面字 + 约 $98.5$ 个头/间隔字 + 首尾边界 ≈ 200 上下，与实测 **204** 吻合。\n",
    "\n",
    "密度升到 1% 时同一算式给 $1 - 0.99^{32} = 0.27510$，字面字期望 860 个；按\"每个字面字配一个间隔字\"估是 1720，但实测只有 **1532**——因为密度上升后相邻字面字连成一片，共享头字。**这说明 WAH 的字数由\"字面字的游程结构\"决定，不只是字面字的个数。**\n",
    "\n",
    "</details>\n",
    "\n",
    "<details>\n",
    "<summary><b>第 5 题</b>：为什么聚簇分布下的 WAH 字数几乎与密度无关（一直是 5 个字左右）？一条连续块被编码成哪几个字？</summary>\n",
    "\n",
    "聚簇位序列长这样（一整段连续的 1，其余全 0）：\n",
    "\n",
    "```text\n",
    "0 … 0 | 1 1 1 … 1 1 1 | 0 … 0\n",
    " └ 前导全 0 字 ┘ └ 若干全 1 字 + 最多两个混杂字 ┘ └ 尾随全 0 字 ┘\n",
    "```\n",
    "\n",
    "编码结果：\n",
    "\n",
    "```text\n",
    "1 个 0-fill 字（覆盖前导的全部 0 字）\n",
    "1~2 个字面字（块的头尾不对齐时才有；恰好字对齐则没有）\n",
    "1 个 1-fill 字（覆盖块内部的全 1 字）\n",
    "1 个 0-fill 字（覆盖尾随的 0 字）\n",
    "```\n",
    "\n",
    "**字数是常数，与块的长度无关**——这正是游程编码的本质。实测拿到 5 个字，说明这批数据的块边界没有字对齐，头尾各多出一个字面字。\n",
    "\n",
    "实践含义非常重要：**把表按某个键排序（cluster）之后再建位图，压缩率会有数量级的改善。** 多维聚簇、Z 序曲线之所以有用，根源也在这里。\n",
    "\n",
    "</details>\n",
    "\n",
    "<details>\n",
    "<summary><b>第 6 题</b>：范围编码构造出的 R_i 之间满足什么单调关系？这个关系对\"更新一行数据\"意味着什么代价？</summary>\n",
    "\n",
    "由定义直接得到包含关系：\n",
    "\n",
    "$$R_1 \\subseteq R_2 \\subseteq \\cdots \\subseteq R_d \\quad (\\text{因为 } A \\le v_i \\Rightarrow A \\le v_{i+1})$$\n",
    "\n",
    "好处是任意区间查询都能用两三次运算凑出来：\n",
    "\n",
    "```text\n",
    "A ≤ v_i        →  R_i\n",
    "A = v_i        →  R_i & ~R_{i−1}\n",
    "v_i < A ≤ v_j  →  R_j & ~R_i\n",
    "```\n",
    "\n",
    "坏处在更新：把 $A[j]$ 从 $v_a$ 改成 $v_b$（设 $v_a < v_b$），那么 $R_a, R_{a+1}, \\ldots, R_{b-1}$ 这 $(b-a)$ 条位序列的第 j 位都要翻转，**代价与取值距离成正比**。对比等值编码：同一行更新只碰 2 条位序列。\n",
    "\n",
    "这就是范围编码的定位：**适合只读为主的分析型负载（OLAP），不适合高频点更新（OLTP）。**\n",
    "\n",
    "</details>\n",
    "\n",
    "<details>\n",
    "<summary><b>第 7 题</b>：本实验的位图查询快，是因为用 <code>bin(x).count(\"1\")</code>（或 <code>int.bit_count()</code>）只数数量。如果要求\"返回命中的所有行号\"，代价会变成什么？复杂度是多少？</summary>\n",
    "\n",
    "统计数量只需一次 popcount。要拿行号就得把每个置位的位置找出来：\n",
    "\n",
    "```python\n",
    "def set_positions(x: int):\n",
    "    '''返回整数 x 中所有为 1 的位下标（从低位向高位）。'''\n",
    "    pos = []\n",
    "    while x:\n",
    "        lsb = x & -x                  # 取出最低的一个置位\n",
    "        pos.append(lsb.bit_length() - 1)\n",
    "        x ^= lsb                      # 清掉这位\n",
    "    return pos\n",
    "```\n",
    "\n",
    "**复杂度是 $O(h)$，$h$ 为命中行数**（每个输出一次循环），而不是 $O(N)$。\n",
    "\n",
    "千万别写成 `[(mask >> i) & 1 for i in range(n)]`——那是 $O(N)$，会把位图查询的优势全丢掉。\n",
    "\n",
    "还有一层：拿到行号之后要去堆表回表取完整记录，**那才是真正的大头**。数量统计只是\"最便宜的那种位图查询\"。\n",
    "\n",
    "</details>\n",
    "\n",
    "<details>\n",
    "<summary><b>第 8 题</b>：位图索引适合低基数列。如果给一列 100% 唯一的键（例如主键）建等值位图，空间会是多大？用 N = 500 000 算一算，为什么这种情况要用 B+ 树或哈希索引？</summary>\n",
    "\n",
    "一列有 $V$ 个不同取值就要 $V$ 条位序列，每条 $N$ 位，总位数 $= V \\cdot N$。\n",
    "\n",
    "$V = N = 500\\,000$ 时：\n",
    "\n",
    "```text\n",
    "总位数 = 500 000 × 500 000 = 2.5 × 10^11 bit\n",
    "       = 2.5 × 10^11 / 8 字节 = 3.125 × 10^10 字节\n",
    "       ≈ 31.25 GB（按 10^9 换算）/ 29.1 GiB（按 2^30 换算）\n",
    "```\n",
    "\n",
    "而原始数据区区几十 MB——**空间放大了几千倍。**\n",
    "\n",
    "所以：\n",
    "\n",
    "- **低基数列**（性别、城市、状态码）适合位图：$V$ 小 ⇒ $V \\cdot N$ 小，而且 $V$ 条位序列足够表达；\n",
    "- **高基数列**（主键、身份证号、时间戳）要用 B+ 树或哈希索引，它们的空间是 $O(N)$ 而不是 $O(N \\cdot V)$。经验阈值视系统而定，通常 $V$ 到几千以上就要重新考虑。\n",
    "\n",
    "</details>"
   ],
   "id": "f2206a7d"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
