初识 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_time、from、to、value、gas_price 等等。
再进阶一点:查一下某个地址最近 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
这段代码干了三件事:
- 从
token_transfers里筛选出 USDC 的转账记录 - 把金额从 wei 转换成 USDC 单位(除以 1e6)
- 按发送方分组,统计每个地址转出了多少 USDC
运行结果会告诉你:谁是 USDC 的「大户」。我经常用这种查询来筛选潜力代币——如果一个代币的前 10 大持有者都是交易所或做市商,那这个代币的流动性风险就比较低。
知识体系结构图
下面这张图帮你理清 Dune V2 的数据模型和查询逻辑:
这张图展示了 Dune V2 的数据流向:从以太坊原始数据,经过三张核心表,再到 SQL 查询,最后输出分析结果。你想想看,整个流程其实就三步:选表、写 SQL、看结果。
ethereum.transactions 玩熟,查查自己的地址、看看某个 DEX 的交易量。等你对字段熟悉了,再开始做跨表 JOIN。我当初就是太心急,一上来就想分析 MEV 机器人,结果被各种 JOIN 搞得头大。
好了,这一章的内容就到这里。记住三张核心表的名字和用途,打开 Dune 的查询编辑器,把上面的代码跑一遍。数据不会骗人,跑通了你就懂了。