mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-12-14 18:32:29 +00:00
393 lines
17 KiB
Markdown
393 lines
17 KiB
Markdown
---
|
||
slug: /ja/getting-started/example-datasets/stackoverflow
|
||
sidebar_label: Stack Overflow
|
||
sidebar_position: 1
|
||
description: Stack OverflowデータのClickHouseによる分析
|
||
---
|
||
|
||
# Stack OverflowデータのClickHouseによる分析
|
||
|
||
このデータセットには、Stack Overflowで行われたすべての`Posts`、`Users`、`Votes`、`Comments`、`Badges`、`PostHistory`、`PostLinks`が含まれています。
|
||
|
||
ユーザーは、2024年4月までのすべての投稿を含む、事前準備されたParquet形式のデータをダウンロードするか、最新のデータをXML形式でダウンロードして読み込むことができます。Stack Overflowは、過去には3ヶ月ごとに、このデータを定期的に更新しています。
|
||
|
||
次の図は、Parquet形式を前提とした利用可能なテーブルのスキーマを示しています。
|
||
|
||
![Stack Overflow schema](./images/stackoverflow.png)
|
||
|
||
このデータのスキーマの説明は[こちら](https://meta.stackexchange.com/questions/2677/database-schema-documentation-for-the-public-data-dump-and-sede)で確認できます。
|
||
|
||
## 事前準備されたデータ
|
||
|
||
Parquet形式で2024年4月まで最新の状態に更新したこのデータのコピーを提供します。このデータセットは、ClickHouseにとって行数(6000万件の投稿)に関しては小さいですが、膨大なテキストと大きなStringカラムが含まれています。
|
||
|
||
```sql
|
||
CREATE DATABASE stackoverflow
|
||
```
|
||
|
||
以下のタイミングは、`eu-west-2`にある96 GiB、24 vCPUのClickHouse Cloudクラスターを対象にしています。データセットは`eu-west-3`にあります。
|
||
|
||
### Posts
|
||
|
||
```sql
|
||
CREATE TABLE stackoverflow.posts
|
||
(
|
||
`Id` Int32 CODEC(Delta(4), ZSTD(1)),
|
||
`PostTypeId` Enum8('Question' = 1, 'Answer' = 2, 'Wiki' = 3, 'TagWikiExcerpt' = 4, 'TagWiki' = 5, 'ModeratorNomination' = 6, 'WikiPlaceholder' = 7, 'PrivilegeWiki' = 8),
|
||
`AcceptedAnswerId` UInt32,
|
||
`CreationDate` DateTime64(3, 'UTC'),
|
||
`Score` Int32,
|
||
`ViewCount` UInt32 CODEC(Delta(4), ZSTD(1)),
|
||
`Body` String,
|
||
`OwnerUserId` Int32,
|
||
`OwnerDisplayName` String,
|
||
`LastEditorUserId` Int32,
|
||
`LastEditorDisplayName` String,
|
||
`LastEditDate` DateTime64(3, 'UTC') CODEC(Delta(8), ZSTD(1)),
|
||
`LastActivityDate` DateTime64(3, 'UTC'),
|
||
`Title` String,
|
||
`Tags` String,
|
||
`AnswerCount` UInt16 CODEC(Delta(2), ZSTD(1)),
|
||
`CommentCount` UInt8,
|
||
`FavoriteCount` UInt8,
|
||
`ContentLicense` LowCardinality(String),
|
||
`ParentId` String,
|
||
`CommunityOwnedDate` DateTime64(3, 'UTC'),
|
||
`ClosedDate` DateTime64(3, 'UTC')
|
||
)
|
||
ENGINE = MergeTree
|
||
PARTITION BY toYear(CreationDate)
|
||
ORDER BY (PostTypeId, toDate(CreationDate), CreationDate)
|
||
|
||
INSERT INTO stackoverflow.posts SELECT * FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/stackoverflow/parquet/posts/*.parquet')
|
||
|
||
0 rows in set. Elapsed: 265.466 sec. Processed 59.82 million rows, 38.07 GB (225.34 thousand rows/s., 143.42 MB/s.)
|
||
```
|
||
|
||
投稿は、年ごとにも利用可能です。例:[https://datasets-documentation.s3.eu-west-3.amazonaws.com/stackoverflow/parquet/posts/2020.parquet](https://datasets-documentation.s3.eu-west-3.amazonaws.com/stackoverflow/parquet/posts/2020.parquet)
|
||
|
||
### Votes
|
||
|
||
```sql
|
||
CREATE TABLE stackoverflow.votes
|
||
(
|
||
`Id` UInt32,
|
||
`PostId` Int32,
|
||
`VoteTypeId` UInt8,
|
||
`CreationDate` DateTime64(3, 'UTC'),
|
||
`UserId` Int32,
|
||
`BountyAmount` UInt8
|
||
)
|
||
ENGINE = MergeTree
|
||
ORDER BY (VoteTypeId, CreationDate, PostId, UserId)
|
||
|
||
INSERT INTO stackoverflow.votes SELECT * FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/stackoverflow/parquet/votes/*.parquet')
|
||
|
||
0 rows in set. Elapsed: 21.605 sec. Processed 238.98 million rows, 2.13 GB (11.06 million rows/s., 98.46 MB/s.)
|
||
```
|
||
|
||
投票は、年ごとにも利用可能です。例:[https://datasets-documentation.s3.eu-west-3.amazonaws.com/stackoverflow/parquet/posts/2020.parquet](https://datasets-documentation.s3.eu-west-3.amazonaws.com/stackoverflow/parquet/votes/2020.parquet)
|
||
|
||
### Comments
|
||
|
||
```sql
|
||
CREATE TABLE stackoverflow.comments
|
||
(
|
||
`Id` UInt32,
|
||
`PostId` UInt32,
|
||
`Score` UInt16,
|
||
`Text` String,
|
||
`CreationDate` DateTime64(3, 'UTC'),
|
||
`UserId` Int32,
|
||
`UserDisplayName` LowCardinality(String)
|
||
)
|
||
ENGINE = MergeTree
|
||
ORDER BY CreationDate
|
||
|
||
INSERT INTO stackoverflow.comments SELECT * FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/stackoverflow/parquet/comments/*.parquet')
|
||
|
||
0 rows in set. Elapsed: 56.593 sec. Processed 90.38 million rows, 11.14 GB (1.60 million rows/s., 196.78 MB/s.)
|
||
```
|
||
|
||
コメントも年ごとに利用可能です。例:[https://datasets-documentation.s3.eu-west-3.amazonaws.com/stackoverflow/parquet/posts/2020.parquet](https://datasets-documentation.s3.eu-west-3.amazonaws.com/stackoverflow/parquet/comments/2020.parquet)
|
||
|
||
### Users
|
||
|
||
```sql
|
||
CREATE TABLE stackoverflow.users
|
||
(
|
||
`Id` Int32,
|
||
`Reputation` LowCardinality(String),
|
||
`CreationDate` DateTime64(3, 'UTC') CODEC(Delta(8), ZSTD(1)),
|
||
`DisplayName` String,
|
||
`LastAccessDate` DateTime64(3, 'UTC'),
|
||
`AboutMe` String,
|
||
`Views` UInt32,
|
||
`UpVotes` UInt32,
|
||
`DownVotes` UInt32,
|
||
`WebsiteUrl` String,
|
||
`Location` LowCardinality(String),
|
||
`AccountId` Int32
|
||
)
|
||
ENGINE = MergeTree
|
||
ORDER BY (Id, CreationDate)
|
||
|
||
INSERT INTO stackoverflow.users SELECT * FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/stackoverflow/parquet/users.parquet')
|
||
|
||
0 rows in set. Elapsed: 10.988 sec. Processed 22.48 million rows, 1.36 GB (2.05 million rows/s., 124.10 MB/s.)
|
||
```
|
||
|
||
### Badges
|
||
|
||
```sql
|
||
CREATE TABLE stackoverflow.badges
|
||
(
|
||
`Id` UInt32,
|
||
`UserId` Int32,
|
||
`Name` LowCardinality(String),
|
||
`Date` DateTime64(3, 'UTC'),
|
||
`Class` Enum8('Gold' = 1, 'Silver' = 2, 'Bronze' = 3),
|
||
`TagBased` Bool
|
||
)
|
||
ENGINE = MergeTree
|
||
ORDER BY UserId
|
||
|
||
INSERT INTO stackoverflow.badges SELECT * FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/stackoverflow/parquet/badges.parquet')
|
||
|
||
0 rows in set. Elapsed: 6.635 sec. Processed 51.29 million rows, 797.05 MB (7.73 million rows/s., 120.13 MB/s.)
|
||
```
|
||
|
||
### PostLinks
|
||
|
||
```sql
|
||
CREATE TABLE stackoverflow.postlinks
|
||
(
|
||
`Id` UInt64,
|
||
`CreationDate` DateTime64(3, 'UTC'),
|
||
`PostId` Int32,
|
||
`RelatedPostId` Int32,
|
||
`LinkTypeId` Enum8('Linked' = 1, 'Duplicate' = 3)
|
||
)
|
||
ENGINE = MergeTree
|
||
ORDER BY (PostId, RelatedPostId)
|
||
|
||
INSERT INTO stackoverflow.postlinks SELECT * FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/stackoverflow/parquet/postlinks.parquet')
|
||
|
||
0 rows in set. Elapsed: 1.534 sec. Processed 6.55 million rows, 129.70 MB (4.27 million rows/s., 84.57 MB/s.)
|
||
```
|
||
|
||
### PostHistory
|
||
|
||
```sql
|
||
CREATE TABLE stackoverflow.posthistory
|
||
(
|
||
`Id` UInt64,
|
||
`PostHistoryTypeId` UInt8,
|
||
`PostId` Int32,
|
||
`RevisionGUID` String,
|
||
`CreationDate` DateTime64(3, 'UTC'),
|
||
`UserId` Int32,
|
||
`Text` String,
|
||
`ContentLicense` LowCardinality(String),
|
||
`Comment` String,
|
||
`UserDisplayName` String
|
||
)
|
||
ENGINE = MergeTree
|
||
ORDER BY (CreationDate, PostId)
|
||
|
||
INSERT INTO stackoverflow.posthistory SELECT * FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/stackoverflow/parquet/posthistory/*.parquet')
|
||
|
||
0 rows in set. Elapsed: 422.795 sec. Processed 160.79 million rows, 67.08 GB (380.30 thousand rows/s., 158.67 MB/s.)
|
||
```
|
||
|
||
## オリジナルデータセット
|
||
|
||
オリジナルのデータセットは、圧縮済み(7zip)XML形式で[https://archive.org/download/stackexchange](https://archive.org/download/stackexchange)から利用できます。`stackoverflow.com*`プレフィックスが付いたファイルです。
|
||
|
||
### ダウンロード
|
||
|
||
```bash
|
||
wget https://archive.org/download/stackexchange/stackoverflow.com-Badges.7z
|
||
wget https://archive.org/download/stackexchange/stackoverflow.com-Comments.7z
|
||
wget https://archive.org/download/stackexchange/stackoverflow.com-PostHistory.7z
|
||
wget https://archive.org/download/stackexchange/stackoverflow.com-PostLinks.7z
|
||
wget https://archive.org/download/stackexchange/stackoverflow.com-Posts.7z
|
||
wget https://archive.org/download/stackexchange/stackoverflow.com-Users.7z
|
||
wget https://archive.org/download/stackexchange/stackoverflow.com-Votes.7z
|
||
```
|
||
|
||
これらのファイルは最大35GBまであり、インターネット接続によってはダウンロードに約30分かかることがあります。ダウンロードサーバーは約20MB/secで制限されています。
|
||
|
||
### JSONへの変換
|
||
|
||
執筆時点で、ClickHouseは入力フォーマットとしてXMLをネイティブにサポートしていません。ClickHouseにデータをロードするには、まずNDJSONに変換します。
|
||
|
||
XMLをJSONに変換するには、XMLドキュメント用のシンプルな`jq`ラッパーツールである[`xq`](https://github.com/kislyuk/yq)をお勧めします。
|
||
|
||
xqとjqのインストール:
|
||
|
||
```bash
|
||
sudo apt install jq
|
||
pip install yq
|
||
```
|
||
|
||
以下の手順は上記の任意のファイルに適用されます。ここでは`stackoverflow.com-Posts.7z`ファイルを例に使用します。必要に応じて修正してください。
|
||
|
||
[p7zip](https://p7zip.sourceforge.net/)を使用してファイルを抽出します。これにより単一のxmlファイルが生成されます。今回の場合は`Posts.xml`です。
|
||
|
||
> ファイルは約4.5倍圧縮されています。22GB圧縮時、投稿ファイルは約97G非圧縮で必要です。
|
||
|
||
```bash
|
||
p7zip -d stackoverflow.com-Posts.7z
|
||
```
|
||
|
||
以下はxmlファイルを10000行ずつのファイルに分割します。
|
||
|
||
```bash
|
||
mkdir posts
|
||
cd posts
|
||
# 以下は入力xmlファイルを10000行のサブファイルに分割します。
|
||
tail +3 ../Posts.xml | head -n -1 | split -l 10000 --filter='{ printf "<rows>\n"; cat - ; printf "</rows>\n"; } > $FILE' -
|
||
```
|
||
|
||
上記を実行すると、ユーザーはそれぞれ10000行のファイルをセットで取得できます。これにより、次のコマンドのメモリオーバーヘッドが過度にならないことが保証されます(XMLからJSONへの変換はメモリ内で行われます)。
|
||
|
||
```bash
|
||
find . -maxdepth 1 -type f -exec xq -c '.rows.row[]' {} \; | sed -e 's:"@:":g' > posts_v2.json
|
||
```
|
||
|
||
上記のコマンドは単一の`posts.json`ファイルを生成します。
|
||
|
||
次のコマンドでClickHouseにロードします。`posts.json`ファイルのスキーマが指定されている点に注意してください。データタイプに応じて、ターゲットテーブルに対する適用が必要です。
|
||
|
||
```bash
|
||
clickhouse local --query "SELECT * FROM file('posts.json', JSONEachRow, 'Id Int32, PostTypeId UInt8, AcceptedAnswerId UInt32, CreationDate DateTime64(3, \'UTC\'), Score Int32, ViewCount UInt32, Body String, OwnerUserId Int32, OwnerDisplayName String, LastEditorUserId Int32, LastEditorDisplayName String, LastEditDate DateTime64(3, \'UTC\'), LastActivityDate DateTime64(3, \'UTC\'), Title String, Tags String, AnswerCount UInt16, CommentCount UInt8, FavoriteCount UInt8, ContentLicense String, ParentId String, CommunityOwnedDate DateTime64(3, \'UTC\'), ClosedDate DateTime64(3, \'UTC\')') FORMAT Native" | clickhouse client --host <host> --secure --password <password> --query "INSERT INTO stackoverflow.posts_v2 FORMAT Native"
|
||
```
|
||
|
||
## クエリ例
|
||
|
||
いくつかの簡単な質問をして、始める手助けをします。
|
||
|
||
### Stack Overflowの最も人気のあるタグ
|
||
|
||
```sql
|
||
|
||
SELECT
|
||
arrayJoin(arrayFilter(t -> (t != ''), splitByChar('|', Tags))) AS Tags,
|
||
count() AS c
|
||
FROM stackoverflow.posts
|
||
GROUP BY Tags
|
||
ORDER BY c DESC
|
||
LIMIT 10
|
||
|
||
┌─Tags───────┬───────c─┐
|
||
│ javascript │ 2527130 │
|
||
│ python │ 2189638 │
|
||
│ java │ 1916156 │
|
||
│ c# │ 1614236 │
|
||
│ php │ 1463901 │
|
||
│ android │ 1416442 │
|
||
│ html │ 1186567 │
|
||
│ jquery │ 1034621 │
|
||
│ c++ │ 806202 │
|
||
│ css │ 803755 │
|
||
└────────────┴─────────┘
|
||
|
||
10 rows in set. Elapsed: 1.013 sec. Processed 59.82 million rows, 1.21 GB (59.07 million rows/s., 1.19 GB/s.)
|
||
Peak memory usage: 224.03 MiB.
|
||
```
|
||
|
||
### 最も回答の多いユーザー(アクティブアカウント)
|
||
|
||
アカウントには`UserId`が必要です。
|
||
|
||
```sql
|
||
SELECT
|
||
any(OwnerUserId) UserId,
|
||
OwnerDisplayName,
|
||
count() AS c
|
||
FROM stackoverflow.posts WHERE OwnerDisplayName != '' AND PostTypeId='Answer' AND OwnerUserId != 0
|
||
GROUP BY OwnerDisplayName
|
||
ORDER BY c DESC
|
||
LIMIT 5
|
||
|
||
┌─UserId─┬─OwnerDisplayName─┬────c─┐
|
||
│ 22656 │ Jon Skeet │ 2727 │
|
||
│ 23354 │ Marc Gravell │ 2150 │
|
||
│ 12950 │ tvanfosson │ 1530 │
|
||
│ 3043 │ Joel Coehoorn │ 1438 │
|
||
│ 10661 │ S.Lott │ 1087 │
|
||
└────────┴──────────────────┴──────┘
|
||
|
||
5 rows in set. Elapsed: 0.154 sec. Processed 35.83 million rows, 193.39 MB (232.33 million rows/s., 1.25 GB/s.)
|
||
Peak memory usage: 206.45 MiB.
|
||
```
|
||
|
||
### ClickHouse関連の投稿で最も多くの閲覧数
|
||
|
||
```sql
|
||
SELECT
|
||
Id,
|
||
Title,
|
||
ViewCount,
|
||
AnswerCount
|
||
FROM stackoverflow.posts
|
||
WHERE Title ILIKE '%ClickHouse%'
|
||
ORDER BY ViewCount DESC
|
||
LIMIT 10
|
||
|
||
┌───────Id─┬─Title────────────────────────────────────────────────────────────────────────────┬─ViewCount─┬─AnswerCount─┐
|
||
│ 52355143 │ Is it possible to delete old records from clickhouse table? │ 41462 │ 3 │
|
||
│ 37954203 │ Clickhouse Data Import │ 38735 │ 3 │
|
||
│ 37901642 │ Updating data in Clickhouse │ 36236 │ 6 │
|
||
│ 58422110 │ Pandas: How to insert dataframe into Clickhouse │ 29731 │ 4 │
|
||
│ 63621318 │ DBeaver - Clickhouse - SQL Error [159] .. Read timed out │ 27350 │ 1 │
|
||
│ 47591813 │ How to filter clickhouse table by array column contents? │ 27078 │ 2 │
|
||
│ 58728436 │ How to search the string in query with case insensitive on Clickhouse database? │ 26567 │ 3 │
|
||
│ 65316905 │ Clickhouse: DB::Exception: Memory limit (for query) exceeded │ 24899 │ 2 │
|
||
│ 49944865 │ How to add a column in clickhouse │ 24424 │ 1 │
|
||
│ 59712399 │ How to cast date Strings to DateTime format with extended parsing in ClickHouse? │ 22620 │ 1 │
|
||
└──────────┴──────────────────────────────────────────────────────────────────────────────────┴───────────┴─────────────┘
|
||
|
||
10 rows in set. Elapsed: 0.472 sec. Processed 59.82 million rows, 1.91 GB (126.63 million rows/s., 4.03 GB/s.)
|
||
Peak memory usage: 240.01 MiB.
|
||
```
|
||
|
||
### 最も議論を呼ぶ投稿
|
||
|
||
```sql
|
||
SELECT
|
||
Id,
|
||
Title,
|
||
UpVotes,
|
||
DownVotes,
|
||
abs(UpVotes - DownVotes) AS Controversial_ratio
|
||
FROM stackoverflow.posts
|
||
INNER JOIN
|
||
(
|
||
SELECT
|
||
PostId,
|
||
countIf(VoteTypeId = 2) AS UpVotes,
|
||
countIf(VoteTypeId = 3) AS DownVotes
|
||
FROM stackoverflow.votes
|
||
GROUP BY PostId
|
||
HAVING (UpVotes > 10) AND (DownVotes > 10)
|
||
) AS votes ON posts.Id = votes.PostId
|
||
WHERE Title != ''
|
||
ORDER BY Controversial_ratio ASC
|
||
LIMIT 3
|
||
|
||
┌───────Id─┬─Title─────────────────────────────────────────────┬─UpVotes─┬─DownVotes─┬─Controversial_ratio─┐
|
||
│ 583177 │ VB.NET Infinite For Loop │ 12 │ 12 │ 0 │
|
||
│ 9756797 │ Read console input as enumerable - one statement? │ 16 │ 16 │ 0 │
|
||
│ 13329132 │ What's the point of ARGV in Ruby? │ 22 │ 22 │ 0 │
|
||
└──────────┴───────────────────────────────────────────────────┴─────────┴───────────┴─────────────────────┘
|
||
|
||
3 rows in set. Elapsed: 4.779 sec. Processed 298.80 million rows, 3.16 GB (62.52 million rows/s., 661.05 MB/s.)
|
||
Peak memory usage: 6.05 GiB.
|
||
```
|
||
|
||
## 帰属
|
||
|
||
このデータを提供してくれたStack Overflowに感謝します。このデータは`cc-by-sa 4.0`ライセンスの下で提供されており、[https://archive.org/details/stackexchange](https://archive.org/details/stackexchange)で元のデータソースに感謝します。
|