初识 Dune Analytics:从数据模型到实战查询

说实话,我第一次接触 Dune Analytics 的时候,也被它的 V2 引擎搞得有点懵。那时候我还在手动爬链上数据,每天跟 RPC 节点较劲。后来发现 Dune 已经把大部分脏活累活都干完了——你只需要会写 SQL,就能直接查询链上数据。

这一章,我带你把 Dune 的底裤扒开看看。说白了,就是搞清楚它的数据是怎么组织的,以及我们怎么用查询编辑器去捞数据。

Dune V2 引擎:数据模型的核心变化

2022 年 Dune 推出了 V2 引擎,这是一个重大的架构升级。我个人习惯把 V2 理解为「把原始数据拆得更细了」。以前 V1 版本里,很多数据是预聚合好的,查询快但灵活性差。V2 不一样,它保留了最原始的链上数据,让你自己组装。

为什么会这样?因为链上数据分析的需求千奇百怪。你想想看,有人想看 Uniswap 的 swap 量,有人想看某个地址的交互图谱,还有人想分析 MEV 机器人——预聚合根本满足不了所有人。V2 把数据拆成原子级别,你爱怎么拼就怎么拼。

核心变化总结:
  • V1:预聚合表,查询快但死板
  • V2:原始数据表,灵活但需要自己写 SQL 聚合
  • V2 支持更复杂的 JOIN 操作,跨合约分析更方便

我在项目中遇到过一个问题:用 V1 查某个代币的转账记录,发现数据对不上。后来才发现 V1 的预聚合表只统计了部分交易类型。换成 V2 的原始表之后,数据才完全准确。嗯,这里要注意——如果你发现数据有偏差,先检查是不是用了 V1 的表。

查询编辑器基础:你的第一个 SQL 查询

Dune 的查询编辑器长什么样?说白了就是一个网页版的 SQL 编辑器,左边写代码,右边出结果。我建议你打开 Dune 的 Query Editor 页面,跟着我敲一遍。

先来个最简单的:查一下以太坊上最近 10 笔交易。

SELECT *
FROM ethereum.transactions
ORDER BY block_time DESC
LIMIT 10

这段代码干了什么?ethereum.transactions 是 Dune 里最常用的表之一,记录了以太坊上每一笔交易。我们按时间倒序排,取前 10 条。运行之后,你会看到一堆字段:block_timefromtovaluegas_price 等等。

小技巧: 在 Dune 的查询编辑器里,按 Ctrl+Enter 运行查询,按 Ctrl+Shift+Enter 格式化 SQL。我刚开始用的时候经常忘记格式化,代码写得跟鬼画符一样。

再进阶一点:查一下某个地址最近 100 笔交易,只看转出的。

SELECT block_time, hash, to, value / 1e18 AS eth_value
FROM ethereum.transactions
WHERE "from" = '0x你的地址'
ORDER BY block_time DESC
LIMIT 100

注意这里我把 value 除以 1e18,因为链上存储的金额单位是 wei,1 ETH = 10^18 wei。这个坑我踩过——第一次查的时候没除,看到一笔交易 value 是 1000000000000000000,还以为是谁转了 100 万个 ETH,吓我一跳。

常用数据表介绍:三张核心表

Dune V2 里表很多,但常用的就那几张。我挑三个最核心的讲,你先把这三张表玩熟,后面再慢慢扩展。

1. ethereum.transactions

这张表记录了以太坊上每一笔交易。字段包括:

字段名 类型 说明
block_time timestamp 交易被打包的时间
from string 发送方地址
to string 接收方地址(合约或 EOA)
value uint256 转账金额(单位:wei)
gas_price uint256 Gas 价格(单位:wei)
success boolean 交易是否成功

这张表我用的最多。比如分析某个地址的 Gas 消耗,或者看大户的转账行为,都离不开它。

2. ethereum.token_transfers

这张表记录的是 ERC-20 代币的转账事件。注意,它不记录 ETH 转账——ETH 转账在 ethereum.transactions 里。

字段包括:

字段名 类型 说明
block_time timestamp 转账时间
token_address string 代币合约地址
from string 转出方
to string 接收方
value uint256 转账数量(注意:精度因代币而异)
避坑指南: 我曾经犯过一个低级错误——直接用 value 字段做聚合,没考虑代币精度。USDC 是 6 位小数,UNI 是 18 位小数。如果你直接 sum(value),结果会完全乱掉。正确的做法是:value / POWER(10, decimals),其中 decimals 需要从代币合约里查。

3. ethereum.contracts

这张表记录了所有已部署的合约信息。字段比较简单:

字段名 类型 说明
address string 合约地址
namespace string 合约命名空间(如 uniswap、makerdao)
name string 合约名称
abi string 合约 ABI(JSON 格式)

这张表有什么用?比如你想查某个地址是不是合约,或者想找某个协议的所有合约地址,都可以用它。

-- 查一下 Uniswap 在以太坊上有哪些合约
SELECT address, name
FROM ethereum.contracts
WHERE namespace = 'uniswap'
LIMIT 20

实战:三张表联合查询

光看单表没意思,我们来个联合查询。假设我想分析某个代币(比如 USDC)的大户转账行为:

WITH usdc_transfers AS (
  SELECT 
    block_time,
    "from",
    "to",
    value / 1e6 AS amount_usdc  -- USDC 是 6 位小数
  FROM ethereum.token_transfers
  WHERE token_address = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'  -- USDC 合约地址
    AND block_time >= '2024-01-01'
)
SELECT 
  "from" AS sender,
  COUNT(*) AS tx_count,
  SUM(amount_usdc) AS total_sent
FROM usdc_transfers
GROUP BY "from"
ORDER BY total_sent DESC
LIMIT 10

这段代码干了三件事:

  1. token_transfers 里筛选出 USDC 的转账记录
  2. 把金额从 wei 转换成 USDC 单位(除以 1e6)
  3. 按发送方分组,统计每个地址转出了多少 USDC

运行结果会告诉你:谁是 USDC 的「大户」。我经常用这种查询来筛选潜力代币——如果一个代币的前 10 大持有者都是交易所或做市商,那这个代币的流动性风险就比较低。

知识体系结构图

下面这张图帮你理清 Dune V2 的数据模型和查询逻辑:

Dune V2 数据模型与查询体系 以太坊原始数据 ethereum.transactions 每笔交易记录 ethereum.token_transfers ERC-20 转账事件 ethereum.contracts 合约信息与 ABI SQL 查询操作 SELECT / WHERE / GROUP BY / JOIN / ORDER BY 分析结果:图表 / 看板 / CSV 导出

这张图展示了 Dune V2 的数据流向:从以太坊原始数据,经过三张核心表,再到 SQL 查询,最后输出分析结果。你想想看,整个流程其实就三步:选表、写 SQL、看结果。

我的建议: 刚开始别急着写复杂查询。先把 ethereum.transactions 玩熟,查查自己的地址、看看某个 DEX 的交易量。等你对字段熟悉了,再开始做跨表 JOIN。我当初就是太心急,一上来就想分析 MEV 机器人,结果被各种 JOIN 搞得头大。

好了,这一章的内容就到这里。记住三张核心表的名字和用途,打开 Dune 的查询编辑器,把上面的代码跑一遍。数据不会骗人,跑通了你就懂了。

专注资料整理