<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>TimescaleDB &#8211; SRA OSS Tech Blog</title>
	<atom:link href="https://www.sraoss.co.jp/tech-blog/tag/timescaledb/feed/index.xml" rel="self" type="application/rss+xml" />
	<link>https://www.sraoss.co.jp/tech-blog/</link>
	<description>OSS専門の技術ブログ。PostgreSQL、Zabbixを中心に10種類以上のOSSの解説、アップデート情報、運用ヒントを提供。</description>
	<lastBuildDate>Fri, 30 Oct 2026 08:23:54 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.3</generator>

<image>
	<url>https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2018/07/blog-icon-150x150.png</url>
	<title>TimescaleDB &#8211; SRA OSS Tech Blog</title>
	<link>https://www.sraoss.co.jp/tech-blog/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>TimescaleDB による Zabbix の性能改善</title>
		<link>https://www.sraoss.co.jp/tech-blog/zabbix/zabbix-timescaledb/</link>
		
		<dc:creator><![CDATA[彭 博 (Bo Peng)]]></dc:creator>
		<pubDate>Thu, 12 May 2022 01:00:50 +0000</pubDate>
				<category><![CDATA[TimescaleDB]]></category>
		<category><![CDATA[Zabbix]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Zabbix 4.4]]></category>
		<guid isPermaLink="false">https://www.sraoss.co.jp/tech-blog/?p=9736</guid>

					<description><![CDATA[Zabbix では、データベースとして PostgreSQL や MySQL などに対応していますが、バージョン 4.4 から TimescaleDB が正式にサポートされるようになりました。 TimescaleDB は ...]]></description>
										<content:encoded><![CDATA[<p>Zabbix では、データベースとして PostgreSQL や MySQL などに対応していますが、バージョン 4.4 から TimescaleDB が正式にサポートされるようになりました。</p>
<p>TimescaleDB は、時系列データベースの機能を PostgreSQL に追加する拡張モジュールで、自動的にデータを時間単位で分割された小さなテーブルに格納できます。Zabbix のデータベースに TimescaleDB を使用することで、性能向上、ディスク使用量の削減などの効果が期待できます。</p>
<p><span id="more-9736"></span></p>
<p>本記事では、 Zabbix で TimescaleDB を利用するメリット、セットアップ方法、利用上の注意点について紹介します。</p>
<p>&nbsp;</p>
<h2>TimescaleDB のサポート</h2>
<p>TimescaleDB は Zabbix 4.4 から正式にサポートされるようになりました。</p>
<p>TimescaleDB では、時系列データベースの機能を適用した親テーブルをハイパーテーブルと呼び、データは内部的にチャンクと呼ばれる小さなテーブルに分割されます。</p>
<p>具体的には以下のヒストリ・トレンドデータを格納するテーブルをハイパーテーブルに変換し、日付ごとにチャンクが自動的に作成されます。</p>
<ul>
<li>history</li>
<li>history_uint</li>
<li>history_log</li>
<li>history_text</li>
<li>history_str</li>
<li>trends</li>
<li>trends_uint</li>
</ul>
<p>また、Zabbix 5.0 以降では、古くなったチャンクを圧縮し、ファイルサイズを縮小することも可能です。</p>
<h2>Zabbix で TimescaleDB を利用するメリット</h2>
<p>Zabbix で TimescaleDB を利用することで、次のようなメリットが得られます。</p>
<h3>Housekeeper による削除処理の負荷軽減</h3>
<p>Housekeeper とは、保存期間を超えたヒストリ・トレンドやイベント、アラートなどのデータを定期的に削除する機能です。</p>
<p>Housekeeper の削除処理は時間範囲で絞り込んで、1行ずつ <code>DELETE</code> するので、削除するレコード数が多くなればなるほど時間がかかり、データベースへの負荷が高まります。データベースの負荷上昇によって、データの読み取り/書き込みが遅くなり、監視の遅延や誤検知など監視全体に影響を与える可能性があります。</p>
<p>一方、Zabbix で TimescaleDB を利用すると、1行ずつ削除する <code>DELETE</code> に対して、TimescaleDB はチャンク単位でデータを削除するため、非常に高速です。これまでの Housekeeper の削除処理による高負荷問題を解決できます。</p>
<p>NVPS が 300 程度、同様な監視設定の Zabbix サーバで、素の PostgreSQL と TimescaleDB を利用した場合の Housekeeper の負荷を検証してみました。Zabbix サーバとデータベースは同一サーバ上で動作し、環境情報は以下の通りです。</p>
<ul>
<li>OS: RHEL 8.5 (VirtualBox 上の VM)</li>
<li>CPU: 2vCPUs</li>
<li>メモリ: 4GB</li>
</ul>
<p>PostgreSQL の場合は、Housekeeper プロセスのビジー率が 100% まで上がる場合がありました。PostgreSQL と比べて、TimescaleDB の場合は最大でも 20% 以下で大幅に軽減されていることがわかります。<br />
※今回の検証で以下の結果を得ましたが、削除するイベントやアラートなどの量によって Housekeeper プロセスのビジー率が変動します。</p>
<figure id="attachment_9850" aria-describedby="caption-attachment-9850" style="width: 1264px" class="wp-caption alignnone"><img fetchpriority="high" decoding="async" class="size-full wp-image-9850" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/04/Housekeeper-PostgreSQL-1.png" alt="" width="1264" height="552" srcset="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/04/Housekeeper-PostgreSQL-1.png 1264w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/04/Housekeeper-PostgreSQL-1-300x131.png 300w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/04/Housekeeper-PostgreSQL-1-1024x447.png 1024w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/04/Housekeeper-PostgreSQL-1-768x335.png 768w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/04/Housekeeper-PostgreSQL-1-304x133.png 304w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/04/Housekeeper-PostgreSQL-1-282x123.png 282w" sizes="(max-width: 1264px) 100vw, 1264px" /><figcaption id="caption-attachment-9850" class="wp-caption-text">PostgreSQL を利用した場合の Housekeeper プロセスのビジー率</figcaption></figure>
<p>&nbsp;</p>
<figure id="attachment_9851" aria-describedby="caption-attachment-9851" style="width: 1264px" class="wp-caption alignnone"><img decoding="async" class="size-full wp-image-9851" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/04/Housekeeper-TimescaleDB-1.png" alt="" width="1264" height="553" srcset="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/04/Housekeeper-TimescaleDB-1.png 1264w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/04/Housekeeper-TimescaleDB-1-300x131.png 300w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/04/Housekeeper-TimescaleDB-1-1024x448.png 1024w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/04/Housekeeper-TimescaleDB-1-768x336.png 768w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/04/Housekeeper-TimescaleDB-1-304x133.png 304w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/04/Housekeeper-TimescaleDB-1-282x123.png 282w" sizes="(max-width: 1264px) 100vw, 1264px" /><figcaption id="caption-attachment-9851" class="wp-caption-text">TimescaleDB を利用した場合の Housekeeper プロセスのビジー率</figcaption></figure>
<h3>不要領域発生の抑止</h3>
<p>PostgreSQL は追記型アーキテクチャを採用しているため、<code>DELETE</code> を実行しても PostgreSQL が使用するディスク領域サイズは減りません。<code>DELETE</code> はデータを削減することはできますが、不要領域が発生します。不要領域を回収して再利用可能な状態にするには VACUUM が必要になります。</p>
<p>Zabbix で TimescaleDB を利用すると、チャンクごと削除するため、<code>DELETE</code> による不要領域の発生を抑止でき、不要領域を回収するための VACUUM 処理によるオーバーヘッドも削減できます。</p>
<h3>圧縮によるディスク領域の節約</h3>
<p>Zabbix で長期運用すると、収集した監視データによって DB のサイズが肥大化していきます。TimescaleDB の圧縮機能を利用し、一定期間経過したヒストリ・トレンドデータを自動的に圧縮できます。</p>
<p>10GB の <code>history</code> テーブルと <code>history_uint</code> テーブルにおいて、7日を超過したデータを圧縮すると、圧縮前に比べて、ディスク領域はそれぞれ 89% と 95% 削減できました。<code>history_log</code>、<code>history_text</code>、<code>history_str</code> テーブルのレコードは可変長レコードであり、レコードのサイズによって圧縮率が変動します。</p>
<table>
<thead>
<tr>
<th>テーブル</th>
<th>圧縮前</th>
<th>圧縮後</th>
<th>圧縮率</th>
</tr>
</thead>
<tbody>
<tr>
<td>history</td>
<td>10GB</td>
<td>1175MB</td>
<td>89%</td>
</tr>
<tr>
<td>history_uint</td>
<td>10GB</td>
<td>466MB</td>
<td>95%</td>
</tr>
</tbody>
</table>
<h3>書き込み性能の向上</h3>
<p>TimescaleDB では、チャンクごとにインデックスを構築するため、インデックスのサイズが小さくなります。また、TimescaleDB は最新のチャンクのデータとインデックスをメモリに保存するため、データ挿入時のインデックスの更新が高速になり、書き込み性能が向上します。</p>
<h2>TimescaleDB のインストール・設定</h2>
<p>この節では、Zabbix のデータベースとして TimescaleDB を利用するためのインストール・設定手順を説明します。</p>
<h3>検証環境</h3>
<p>今回は以下の構成でインストールを行います。各ソフトウェアは 2022 年 5 月時点での最新バージョンを利用しています。</p>
<ul>
<li>OS: RHEL 8.5</li>
<li>Zabbix 6.0.3</li>
<li>PostgreSQL 14.2</li>
<li>TimescaleDB 2.6.1</li>
</ul>
<p>TimescaleDB は 2022 年 5 月時点で以下のバージョンがメンテナンスされており、それぞれ対応する PostgreSQL のバージョンは以下の通りです。</p>
<table>
<thead>
<tr>
<th>TimescaleDB バージョン</th>
<th>対応 PostgreSQL バージョン</th>
</tr>
</thead>
<tbody>
<tr>
<td>2.5 以降</td>
<td>12、13、14</td>
</tr>
<tr>
<td>2.4</td>
<td>12、13</td>
</tr>
<tr>
<td>2.1～2.3</td>
<td>12、13</td>
</tr>
<tr>
<td>2.0</td>
<td>11、12</td>
</tr>
<tr>
<td>1.7</td>
<td>9.6、10、11、12</td>
</tr>
</tbody>
</table>
<h3>前提条件</h3>
<p>TimescaleDB をインストールする前に、Zabbix サーバと PostgreSQL がすでにインストールされており、データベースの初期設定、データベーススキーマと初期データの投入が完了していることが前提となります。</p>
<p>まだ完了していない場合は、<a href="https://www.sraoss.co.jp/tech-blog/zabbix/zabbix60-install/">こちら</a>のインストール手順を参照してください。</p>
<h3>TimescaleDB のインストール</h3>
<p>本記事では、RHEL 8 上で構築した PostgreSQL サーバに TimescaleDB をインストールします。他のプラットフォーム向けのインストール方法については TimescaleDB の<a href="https://docs.timescale.com/install/latest/">ドキュメント</a>を参照してください。</p>
<p>TimescaleDB の Yum リポジトリを登録します。</p>
<pre>$ sudo tee /etc/yum.repos.d/timescale_timescaledb.repo &lt;&lt;EOL
[timescale_timescaledb]
name=timescale_timescaledb
baseurl=https://packagecloud.io/timescale/timescaledb/el/$(rpm -E %{rhel})/\$basearch
repo_gpgcheck=1
gpgcheck=0
enabled=1
gpgkey=https://packagecloud.io/timescale/timescaledb/gpgkey
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
metadata_expire=300
EOL</pre>
<p>TimescaleDB の RPM パッケージをインストールします。<br />
※ PostgreSQL xx がインストールされている場合は <code>timescaledb-2-postgresql-xx</code> を指定します。</p>
<pre>$ sudo dnf install timescaledb-2-postgresql-14</pre>
<h3>TimescaleDB の設定</h3>
<p>PostgreSQL で TimescaleDB を利用するための設定を行います。</p>
<p>PostgreSQL の設定ファイル <code>postgresql.conf</code> を直接編集しても良いですが、ここでは、環境のスペックに応じて対話的に PostgreSQL パラメータのチューニングを行う <code>timescaledb-tune</code> コマンドを使います。</p>
<p><code>--pg-config</code> オプションには <code>pg_config</code> コマンドのパスを指定します。その他のオプションについては <code>timescaledb-tune --help</code> で確認できます。<br />
以下のコマンドを実行すると、次々と質問されますが、基本的には y を入力していけば良いです。最後に設定が <code>postgresql.conf</code> に書き込まれます。環境によって、Zabbix で使用するには <code>max_connections</code> の推奨値が小さすぎる可能性があるので、ここでは明示的に <code>max_connections</code> の値を設定します。</p>
<pre>$ sudo timescaledb-tune --pg-config=/usr/pgsql-14/bin/pg_config --max-conns=100</pre>
<p>上記コマンドによって、TimescaleDB が <code>shared_preload_libraries</code> にロードされ、PostgreSQL のパラメータが環境に応じた適切な値に設定されます。</p>
<p>設定変更を反映するため、PostgreSQL のサービスを再起動します。</p>
<pre>$ sudo systemctl restart postgresql-14</pre>
<h3>TimesaceleDB 拡張の作成</h3>
<p>Zabbix サーバが利用する zabbix データベースに TimesaceleDB 拡張をインストールします。</p>
<pre>$ echo "CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;" | sudo -u postgres psql zabbix</pre>
<p><code>/usr/share/doc/zabbix-sql-scripts/postgresql/</code> にある TimescaleDB のスキーマ作成スクリプト <code>timescaledb.sql</code> を実行します。</p>
<pre>$ cat /usr/share/doc/zabbix-sql-scripts/postgresql/timescaledb.sql | sudo -u zabbix psql zabbix</pre>
<p>上記コマンドに指定した <code>timescaledb.sql</code> スクリプトの中身を確認してみましょう。</p>
<pre>(以下、実行不要)
$ cat /usr/share/doc/zabbix-sql-scripts/postgresql/timescaledb.sql
(省略)
<strong><span style="color: #228b22; font-size: small;"># ヒストリ・トレンドテーブルを1日ごとにチャンクを作成するハイパーテーブルに変換。</span></strong>
<strong><span style="color: #228b22; font-size: small;"># ヒストリ・トレンドテーブルに既存のデータがある場合には、既存のデータの移行が行われる。</span></strong>
PERFORM create_hypertable('history', 'clock', chunk_time_interval =&gt; 86400, migrate_data =&gt; true);
PERFORM create_hypertable('history_uint', 'clock', chunk_time_interval =&gt; 86400, migrate_data =&gt; true);
PERFORM create_hypertable('history_log', 'clock', chunk_time_interval =&gt; 86400, migrate_data =&gt; true);
PERFORM create_hypertable('history_text', 'clock', chunk_time_interval =&gt; 86400, migrate_data =&gt; true);
PERFORM create_hypertable('history_str', 'clock', chunk_time_interval =&gt; 86400, migrate_data =&gt; true);
PERFORM create_hypertable('trends', 'clock', chunk_time_interval =&gt; 2592000, migrate_data =&gt; true);
PERFORM create_hypertable('trends_uint', 'clock', chunk_time_interval =&gt; 2592000, migrate_data =&gt; true);

<strong><span style="color: #228b22; font-size: small;"># [管理] -&gt; [一般設定] -&gt; [データの保存期間]ページで「アイテムのヒストリ/トレンドの保存期間設定を上書き」オプションを有効にする。</span></strong>
UPDATE config SET db_extension='timescaledb',hk_history_global=1,hk_trends_global=1;

<strong><span style="color: #228b22; font-size: small;"># 圧縮機能を有効にする。デフォルトでは7日間を超えたデータは自動的に圧縮される。</span></strong>
UPDATE config SET compression_status=1,compress_older='7d';
</pre>
<p>Zabbix サーバのデータベースにアクセスし、history テーブルを確認してみます。</p>
<pre>$ psql -U zabbix
Password for user zabbix: 
psql (14.2)
Type "help" for help.

zabbix=&gt; \d+ history
                                                    Table "public.history"
 Column |       Type       | Collation | Nullable |        Default        | Storage | Compression | Stats target | Description 
--------+------------------+-----------+----------+-----------------------+---------+-------------+--------------+-------------
 itemid | bigint           |           | not null |                       | plain   |             |              | 
 clock  | integer          |           | not null | 0                     | plain   |             |              | 
 value  | double precision |           | not null | '0'::double precision | plain   |             |              | 
 ns     | integer          |           | not null | 0                     | plain   |             |              | 
Indexes:
    "history_pkey" PRIMARY KEY, btree (itemid, clock, ns)
    "history_clock_idx" btree (clock DESC)
Triggers:
    ts_insert_blocker BEFORE INSERT ON history FOR EACH ROW EXECUTE FUNCTION _timescaledb_internal.insert_blocker()
Child tables: _timescaledb_internal._hyper_1_1_chunk
Access method: heap
</pre>
<p>history テーブルがハイパーテーブルに変換されており、チャンク (Child tables) が1つ存在することがわかります。</p>
<p>ヒストリ・トレンドテーブルデータの保存期間や圧縮に関する詳細設定は Web インターフェースの [管理] -&gt; [一般設定] -&gt; [データの保存期間] ページにて設定できます。</p>
<p><code>timescaledb.sql</code> スクリプトを実行すると、以下のような設定となります。</p>
<p><img decoding="async" class="size-full wp-image-9743 aligncenter" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/04/housekeeping.png" alt="" width="1004" height="1041" srcset="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/04/housekeeping.png 1004w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/04/housekeeping-289x300.png 289w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/04/housekeeping-988x1024.png 988w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/04/housekeeping-768x796.png 768w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/04/housekeeping-206x214.png 206w, https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2022/04/housekeeping-251x260.png 251w" sizes="(max-width: 1004px) 100vw, 1004px" /></p>
<p>&nbsp;</p>
<p>「アイテムのヒストリの保存期間設定を上書き」と「アイテムのトレンドの保存期間設定を上書き」にチェックが付いている状態になります。この設定により、ヒストリ・トレンドテーブルにて Housekeeper によるチャンクごとの削除処理が有効になります。また、これらにチェックが入っていると、各アイテムで設定したヒストリとトレンドの保存期間を上書きし、すべてのアイテムで共通のヒストリとトレンドの保存期間を設定できます。</p>
<p>ヒストリとトレンドが圧縮されるまでの期間は「次よりも古いものはレコードを圧縮」にて設定できます。7日以上の値を設定する必要があります。</p>
<h2>TimescaleDB 利用上の注意点</h2>
<p>本節では、Zabbix で TimescaleDB を利用する際の注意点を記載します。</p>
<ul>
<li>TimescaleDB は Zabbix プロキシではサポートされていません。</li>
<li>パーティション化された Housekeeper 処理を利用する場合は、Zabbix サーバで共通のヒストリ・トレンドの保存期間を使用することになるので、アイテム別にヒストリ・トレンドの保存期間を設定できません。</li>
<li>TimescaleDB の圧縮を利用するには、以下の条件が前提となります。
<ul>
<li>Zabbix 5.0 以降</li>
<li>PostgreSQL 10.2 以降</li>
<li>TimescaleDB 1.5 以降</li>
</ul>
</li>
<li>圧縮したヒストリ・トレンドテーブルのデータは参照処理 (SELECT) はできますが、更新処理 (INSERT、UPDATE、DELETE) はできません。また、圧縮した ヒストリ・トレンドテーブルのスキーマ変更はできません。</li>
<li>PostgreSQL から TimescaleDB に移行する場合、既存のヒストリ・トレンドテーブルのデータ量が多ければ多いほど、移行に時間がかかります。データの移行を行う前に、サーバに十分な空き領域があることを確認してください。少なくともヒストリ・トレンドテーブルとインデックスの合計サイズの 1.5 倍の空き領域が必要です。また、移行期間中に、Zabbix サーバと Zabbix フロントエンドを停止する必要があります。</li>
</ul>
<h2>おわりに</h2>
<p>今回は、Zabbix サーバのバックエンドデータベースとして時系列データベース TimescaleDB を利用する際のメリットや注意点、インストール手順について紹介しました。</p>
<p>TimescaleDB を導入することによって、Housekeeper による負荷の軽減や書き込み性能の向上、ディスク使用量の削減などのメリットを得られます。</p>
<p>既存の PostgreSQL から容易に移行でき、これまで PostgreSQL で利用していたバックアップ、リストアなどの運用方式は TimescaleDB でも利用できるので、PostgreSQL を利用していて性能やディスク使用量を改善したい場合は、TimescaleDB を使うことを検討してみてはいかがでしょうか。</p>
<div>
<a href="https://www.sraoss.co.jp/prod_serv/support/pgsql-mainte/?utm_source=sraoss-techblog&utm_medium=referral&utm_campaign=under-article-pgsql" rel="noopener" style="color:initial;" target="_blank" class="no-ext"></p>
<div style="background-color:#DAEFF6; padding:20px; border-radius:8px; text-align:center;">
SRA OSSでは、PostgreSQL/Pgpool-II のサポートを提供しております。<br />
詳しくは<strong style="color:#2581c4;">弊社ホームページ</strong>をご覧ください。
</div>
<p></a>
</div>

]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>TimescaleDB によるデータ分析</title>
		<link>https://www.sraoss.co.jp/tech-blog/pgsql/timescaledb-analysis/</link>
		
		<dc:creator><![CDATA[データベース技術グループ]]></dc:creator>
		<pubDate>Thu, 24 Jun 2021 01:10:49 +0000</pubDate>
				<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[TimescaleDB]]></category>
		<category><![CDATA[サードパーティーソフトウェア]]></category>
		<guid isPermaLink="false">https://www.sraoss.co.jp/tech-blog/?p=7054</guid>

					<description><![CDATA[TimescaleDB は、IoT 機器のセンサーやスマートメーターが生成するデータのように、時系列に沿って発生するデータを扱うのに適した時系列データベースの機能を、リレーショナルデータベース PostgreSQL に追 ...]]></description>
										<content:encoded><![CDATA[<p>TimescaleDB は、IoT 機器のセンサーやスマートメーターが生成するデータのように、時系列に沿って発生するデータを扱うのに適した時系列データベースの機能を、リレーショナルデータベース PostgreSQL に追加する拡張モジュールです。</p>
<p>この記事では、TimescaleDB の備える時系列データ向けの分析機能について紹介します。TimescaleDB の概要やインストール、基本的な使い方については前回の <a href="https://www.sraoss.co.jp/tech-blog/pgsql/timescaledb-intro/">TimescaleDB の紹介</a> を参照してください。</p>
<p><span id="more-7054"></span></p>
<h2>時系列データの分析関数</h2>
<p>TimescaleDB には時系列データの分析に便利な関数がいくつかあります。ここでは、前回生成したデータを使って各関数の概要と使い方について紹介していきます。それには、まず、<code>test</code> データベースに接続しておきます。</p>
<pre>$ psql test
psql (13.2)
"help"でヘルプを表示します。

=#
</pre>
<h2><code>time_bucket</code> 関数</h2>
<p><code>time_bucket</code> 関数は時間を任意の間隔で丸める関数です。同じような関数は PostgreSQL にもあって <code>date_trunc</code> 関数と言います。</p>
<p><code>date_trunc</code> 関数を使うと、例えば、1 分間隔で収集した温度のデータに対し、1 時間ごとの平均を求められます。</p>
<pre>=# SELECT date_trunc('hour', time) AS time_1h,
     location,
     avg(temperature)
   FROM conditions
   GROUP BY time_1h, location
   ORDER BY time_1h, location;
       time_1h       | location |        avg
---------------------+----------+--------------------
 2020-01-30 00:00:00 | nagoya   | 19.883333333333333
 2020-01-30 00:00:00 | osaka    |  20.68333333333333
 2020-01-30 00:00:00 | tokyo    |              20.73
 2020-01-30 01:00:00 | nagoya   |  19.65666666666666
 2020-01-30 01:00:00 | osaka    |              20.82
 2020-01-30 01:00:00 | tokyo    |  20.04000000000001
 2020-01-30 02:00:00 | nagoya   | 18.854999999999993
 2020-01-30 02:00:00 | osaka    |  19.89833333333333
 2020-01-30 02:00:00 | tokyo    | 20.345000000000006
 2020-01-30 03:00:00 | nagoya   | 20.338333333333335
 2020-01-30 03:00:00 | osaka    |             20.395
 2020-01-30 03:00:00 | tokyo    | 20.781666666666673
(省略)
</pre>
<p>同じことは <code>time_bucket</code> 関数でもできます。</p>
<pre>=# SELECT time_bucket('1 hour', time) AS time_1h,
     location,
     avg(temperature)
   FROM conditions
   GROUP BY time_1h, location
   ORDER BY time_1h, location;
       time_1h       | location |        avg
---------------------+----------+--------------------
 2020-01-30 00:00:00 | nagoya   | 19.883333333333333
 2020-01-30 00:00:00 | osaka    |  20.68333333333333
 2020-01-30 00:00:00 | tokyo    |              20.73
 2020-01-30 01:00:00 | nagoya   |  19.65666666666666
 2020-01-30 01:00:00 | osaka    |              20.82
 2020-01-30 01:00:00 | tokyo    |  20.04000000000001
 2020-01-30 02:00:00 | nagoya   | 18.854999999999993
 2020-01-30 02:00:00 | osaka    |  19.89833333333333
 2020-01-30 02:00:00 | tokyo    | 20.345000000000006
 2020-01-30 03:00:00 | nagoya   | 20.338333333333335
 2020-01-30 03:00:00 | osaka    |             20.395
 2020-01-30 03:00:00 | tokyo    | 20.781666666666673
(省略)
</pre>
<p><code>date_trunc</code> 関数と <code>time_bucket</code> 関数の違いは、<code>date_trunc</code> 関数が 1 時間や 1 日など、固定の時間でしか丸められないのに対し、<code>time_bucket</code> 関数は 3 時間や 5 日など、任意の時間で丸められることです。<code>time_bucket</code> 関数を使うと、例えば、3 時間ごとの平均を求められます。</p>
<pre>=# SELECT time_bucket('3 hours', time) AS time_3h,
     location,
     avg(temperature)
   FROM conditions
   GROUP BY time_3h, location
   ORDER BY time_3h, location;
       time_3h       | location |        avg
---------------------+----------+--------------------
 2020-01-30 00:00:00 | nagoya   |             19.465
 2020-01-30 00:00:00 | osaka    |  20.46722222222223
 2020-01-30 00:00:00 | tokyo    | 20.371666666666673
 2020-01-30 03:00:00 | nagoya   | 20.202777777777776
 2020-01-30 03:00:00 | osaka    |  19.89277777777778
 2020-01-30 03:00:00 | tokyo    | 21.122222222222224
 2020-01-30 06:00:00 | nagoya   |  19.99055555555557
 2020-01-30 06:00:00 | osaka    | 19.288333333333338
 2020-01-30 06:00:00 | tokyo    | 19.353333333333335
 2020-01-30 09:00:00 | nagoya   | 20.950000000000003
 2020-01-30 09:00:00 | osaka    | 20.285000000000007
 2020-01-30 09:00:00 | tokyo    | 20.203333333333326
(省略)
</pre>
<h3><code>time_bucket_gapfill</code> 関数</h3>
<p><code>time_bucket_gapfill</code> 関数は <code>time_bucket</code> 関数と同じく時間を任意の間隔で丸める関数ですが、欠落したデータを補ってくれることが異なります。</p>
<p>例えば、2020 年 2 月 1 日、東京のデータを削除し、人為的にデータを欠落させ、<code>time_bucket</code> 関数を使って 3 時間ごとの平均を求めると、6 時、9 時のデータが欠落しているのが分かります。</p>
<pre>=# DELETE FROM conditions
   WHERE time &gt;= '2020-02-01 06:00:00'
     AND time &lt; '2020-02-01 12:00:00' AND location = 'tokyo';
DELETE 360
=# SELECT time_bucket('3 hours', time) AS time_3h, location, avg(temperature) FROM conditions WHERE time &gt;= '2020-02-01'
     AND time &lt; '2020-02-02'
   GROUP BY time_3h, location
   ORDER BY time_3h, location;
       time_3h       | location |        avg
---------------------+----------+--------------------
 2020-02-01 00:00:00 | nagoya   |  19.75833333333333
 2020-02-01 00:00:00 | osaka    |  20.46555555555556
 2020-02-01 00:00:00 | tokyo    | 19.315555555555555
 2020-02-01 03:00:00 | nagoya   | 19.328888888888887
 2020-02-01 03:00:00 | osaka    | 20.167777777777783
 2020-02-01 03:00:00 | tokyo    | 19.592777777777773
 2020-02-01 06:00:00 | nagoya   |  19.87055555555555
 2020-02-01 06:00:00 | osaka    |  20.07277777777777
 2020-02-01 09:00:00 | nagoya   | 19.240555555555563
 2020-02-01 09:00:00 | osaka    |             19.915
 2020-02-01 12:00:00 | nagoya   | 20.018888888888895
 2020-02-01 12:00:00 | osaka    |  19.66388888888888
 2020-02-01 12:00:00 | tokyo    | 19.437777777777782
 2020-02-01 15:00:00 | nagoya   | 19.904444444444444
 2020-02-01 15:00:00 | osaka    |  20.11388888888888
 2020-02-01 15:00:00 | tokyo    | 19.707222222222217
 2020-02-01 18:00:00 | nagoya   | 20.251111111111115
 2020-02-01 18:00:00 | osaka    | 20.023888888888884
 2020-02-01 18:00:00 | tokyo    | 20.571666666666676
 2020-02-01 21:00:00 | nagoya   |  19.91722222222222
 2020-02-01 21:00:00 | osaka    | 20.952777777777772
 2020-02-01 21:00:00 | tokyo    | 19.904444444444447
(22 行)
</pre>
<p><img decoding="async" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2021/06/timescaledb-gap.png" alt="データ欠落" /></p>
<p>それに対し、<code>time_bucket_gapfill</code> 関数を使うと、欠落したデータに <code>NULL</code> が補われるようになります。</p>
<pre>=# SELECT time_bucket_gapfill('3 hours', time) AS time_3h,
     location,
     avg(temperature)
   FROM conditions
   WHERE time &gt;= '2020-02-01'
     AND time &lt; '2020-02-02'
   GROUP BY time_3h, location
   ORDER BY time_3h, location;
       time_3h       | location |        avg
---------------------+----------+--------------------
 2020-02-01 00:00:00 | nagoya   |  19.75833333333333
 2020-02-01 00:00:00 | osaka    |  20.46555555555556
 2020-02-01 00:00:00 | tokyo    | 19.315555555555555
 2020-02-01 03:00:00 | nagoya   | 19.328888888888887
 2020-02-01 03:00:00 | osaka    | 20.167777777777783
 2020-02-01 03:00:00 | tokyo    | 19.592777777777773
 2020-02-01 06:00:00 | nagoya   |  19.87055555555555
 2020-02-01 06:00:00 | osaka    |  20.07277777777777
 2020-02-01 06:00:00 | tokyo    |
 2020-02-01 09:00:00 | nagoya   | 19.240555555555563
 2020-02-01 09:00:00 | osaka    |             19.915
 2020-02-01 09:00:00 | tokyo    |
 2020-02-01 12:00:00 | nagoya   | 20.018888888888895
 2020-02-01 12:00:00 | osaka    |  19.66388888888888
 2020-02-01 12:00:00 | tokyo    | 19.437777777777782
 2020-02-01 15:00:00 | nagoya   | 19.904444444444444
 2020-02-01 15:00:00 | osaka    |  20.11388888888888
 2020-02-01 15:00:00 | tokyo    | 19.707222222222217
 2020-02-01 18:00:00 | nagoya   | 20.251111111111115
 2020-02-01 18:00:00 | osaka    | 20.023888888888884
 2020-02-01 18:00:00 | tokyo    | 20.571666666666676
 2020-02-01 21:00:00 | nagoya   |  19.91722222222222
 2020-02-01 21:00:00 | osaka    | 20.952777777777772
 2020-02-01 21:00:00 | tokyo    | 19.904444444444447
(24 行)
</pre>
<p><code>time_bucket_gapfill</code> 関数を使う場合には、どこからどこまでデータを補うかを指定するため、時間の範囲を <code>WHERE</code> 句か <code>start</code>、<code>finish</code> 引数で指定する必要があります。指定しないとエラーになります。</p>
<pre>(以下、例示のため、実行不要)
=# SELECT time_bucket_gapfill('3 hours', time) AS time_3h,
     location,
     avg(temperature)
   FROM conditions
   GROUP BY time_3h, location
   ORDER BY time_3h, location;
ERROR:  missing time_bucket_gapfill argument: could not infer start from WHERE clause
HINT:  Specify start and finish as arguments or in the WHERE clause.
</pre>
<p><code>NULL</code> の代わりに値を補うこともできます。それには、<code>locf</code> または <code>interpolate</code> 関数を使います。</p>
<p><code>locf</code> (last observation carried forward; 最後に観測された値を繰り越す) 関数を使うと、直前の値がそのまま補われます。ここでは、6 時、9 時には直前の 3 時と同じ 19.592度 (以下、小数点第 4 位以下切り捨て) が補われます。</p>
<pre>=# SELECT time_bucket_gapfill('3 hours', time) AS time_3h,
     location,
     locf(avg(temperature))
   FROM conditions
   WHERE time &gt;= '2020-02-01'
     AND time &lt; '2020-02-02'
   GROUP BY time_3h, location
   ORDER BY time_3h, location;
       time_3h       | location |        locf
---------------------+----------+--------------------
 2020-02-01 00:00:00 | nagoya   |  19.75833333333333
 2020-02-01 00:00:00 | osaka    |  20.46555555555556
 2020-02-01 00:00:00 | tokyo    | 19.315555555555555
 2020-02-01 03:00:00 | nagoya   | 19.328888888888887
 2020-02-01 03:00:00 | osaka    | 20.167777777777783
 2020-02-01 03:00:00 | tokyo    | 19.592777777777773
 2020-02-01 06:00:00 | nagoya   |  19.87055555555555
 2020-02-01 06:00:00 | osaka    |  20.07277777777777
 2020-02-01 06:00:00 | tokyo    | 19.592777777777773
 2020-02-01 09:00:00 | nagoya   | 19.240555555555563
 2020-02-01 09:00:00 | osaka    |             19.915
 2020-02-01 09:00:00 | tokyo    | 19.592777777777773
 2020-02-01 12:00:00 | nagoya   | 20.018888888888895
 2020-02-01 12:00:00 | osaka    |  19.66388888888888
 2020-02-01 12:00:00 | tokyo    | 19.437777777777782
 2020-02-01 15:00:00 | nagoya   | 19.904444444444444
 2020-02-01 15:00:00 | osaka    |  20.11388888888888
 2020-02-01 15:00:00 | tokyo    | 19.707222222222217
 2020-02-01 18:00:00 | nagoya   | 20.251111111111115
 2020-02-01 18:00:00 | osaka    | 20.023888888888884
 2020-02-01 18:00:00 | tokyo    | 20.571666666666676
 2020-02-01 21:00:00 | nagoya   |  19.91722222222222
 2020-02-01 21:00:00 | osaka    | 20.952777777777772
 2020-02-01 21:00:00 | tokyo    | 19.904444444444447
(24 行)
</pre>
<p><img decoding="async" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2021/06/timescaledb-gapfill-locf.png" alt="locf 関数によるデータ補間" /></p>
<p><code>interpolate</code> 関数を使うと、直前と直後の値をもとに線形補間によって値が補われます。ここでは、直前の 3 時は 19.592 度、直後の 12 時は19.437 度で、6 時は線形補間によって19.592 + (19.437 &#8211; 19.592) / 3 = 19.541 度、9 時も同じように 19.592 + (19.437 &#8211; 19.592) × 2 / 3 = 19.489 度が補われます。</p>
<pre>=# SELECT time_bucket_gapfill('3 hours', time) AS time_3h,
     location,
     interpolate(avg(temperature))
   FROM conditions
   WHERE time &gt;= '2020-02-01'
     AND time &lt; '2020-02-02'
   GROUP BY time_3h, location
   ORDER BY time_3h, location;
       time_3h       | location |    interpolate
---------------------+----------+--------------------
 2020-02-01 00:00:00 | nagoya   |  19.75833333333333
 2020-02-01 00:00:00 | osaka    |  20.46555555555556
 2020-02-01 00:00:00 | tokyo    | 19.315555555555555
 2020-02-01 03:00:00 | nagoya   | 19.328888888888887
 2020-02-01 03:00:00 | osaka    | 20.167777777777783
 2020-02-01 03:00:00 | tokyo    | 19.592777777777773
 2020-02-01 06:00:00 | nagoya   |  19.87055555555555
 2020-02-01 06:00:00 | osaka    |  20.07277777777777
 2020-02-01 06:00:00 | tokyo    |  19.54111111111111
 2020-02-01 09:00:00 | nagoya   | 19.240555555555563
 2020-02-01 09:00:00 | osaka    |             19.915
 2020-02-01 09:00:00 | tokyo    | 19.489444444444445
 2020-02-01 12:00:00 | nagoya   | 20.018888888888895
 2020-02-01 12:00:00 | osaka    |  19.66388888888888
 2020-02-01 12:00:00 | tokyo    | 19.437777777777782
 2020-02-01 15:00:00 | nagoya   | 19.904444444444444
 2020-02-01 15:00:00 | osaka    |  20.11388888888888
 2020-02-01 15:00:00 | tokyo    | 19.707222222222217
 2020-02-01 18:00:00 | nagoya   | 20.251111111111115
 2020-02-01 18:00:00 | osaka    | 20.023888888888884
 2020-02-01 18:00:00 | tokyo    | 20.571666666666676
 2020-02-01 21:00:00 | nagoya   |  19.91722222222222
 2020-02-01 21:00:00 | osaka    | 20.952777777777772
 2020-02-01 21:00:00 | tokyo    | 19.904444444444447
(24 行)
</pre>
<p><img decoding="async" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2021/06/timescaledb-gapfill-interpolate.png" alt="interpolate 関数によるデータ補間" /></p>
<h3><code>first</code>、<code>last</code> 関数</h3>
<p><code>first</code>、<code>last</code> 関数は別の列をキーに並び替え、最初、最後の値を取得する集約関数です。時間ごとに平均などでなく、素の値を抜き出すのに使います。並び替えにインデックスは使えないので、実行に時間がかかる場合があります。</p>
<p>例えば、2020 年 3 月 1 日、東京の温度のデータを 3 時間ごとに最初の値を取得してみます。</p>
<pre>=# SELECT time_bucket('3 hours', time) AS time_3h,
     first(temperature, time)
   FROM conditions
   WHERE time &gt;= '2020-03-01'
     AND time &lt; '2020-03-02'
     AND location = 'tokyo'
   GROUP BY time_3h
   ORDER BY time_3h;
       time_3h       | first
---------------------+-------
 2020-03-01 00:00:00 |  24.4
 2020-03-01 03:00:00 |  18.9
 2020-03-01 06:00:00 |  25.1
 2020-03-01 09:00:00 |  22.8
 2020-03-01 12:00:00 |  25.8
 2020-03-01 15:00:00 |  23.1
 2020-03-01 18:00:00 |  11.6
 2020-03-01 21:00:00 |  21.3
(8 行)
</pre>
<h3><code>histogram</code> 関数</h3>
<p><code>histogram</code> 関数はヒストグラムを取得する集約関数です。データの度数分布を確認するのに使います。</p>
<p>例えば、2020 年 3 月 1 日、東京の温度のデータを 3 時間ごとに 12.5 度から 27.5 度まで 2.5 度刻みで 6 つに区切ったヒストグラムを取得してみます。</p>
<pre>=# SELECT time_bucket('3 hours', time) AS time_3h,
     histogram(temperature, 12.5, 27.5, 5)
   FROM conditions
   WHERE time &gt;= '2020-03-01'
     AND time &lt; '2020-03-02'
     AND location = 'tokyo'
   GROUP BY time_3h
   ORDER BY time_3h;
       time_3h       |         histogram
---------------------+---------------------------
 2020-03-01 00:00:00 | {23,16,19,21,29,19,27,26}
 2020-03-01 03:00:00 | {21,17,21,25,25,21,29,21}
 2020-03-01 06:00:00 | {20,29,14,25,22,24,27,19}
 2020-03-01 09:00:00 | {17,24,19,27,18,28,28,19}
 2020-03-01 12:00:00 | {20,17,25,22,31,22,21,22}
 2020-03-01 15:00:00 | {28,23,17,29,25,18,18,22}
 2020-03-01 18:00:00 | {23,14,27,18,30,22,25,21}
 2020-03-01 21:00:00 | {20,20,20,32,19,27,25,17}
(8 行)
</pre>
<p>ヒストグラムは波カッコ <code>{}</code> で囲まれ、カンマ <code>,</code> で区切られた配列として出力されます。配列の各要素が区間内の度数を表します。ここでは、最初の要素が 12.5 度未満、次が 12.5 度以上、15 度未満、その次が 15 度以上、17.5 度未満と続いていき、最後が 27.5 超過のデータの度数になります。</p>
<h3><code>approximate_row_count</code> 関数</h3>
<p><code>approximate_row_count</code> 関数は統計情報を使ってテーブルのおおよその行数を取得する関数です。結果が正確でない代わりに、<code>count</code> 関数に比べて高速に動作します。</p>
<p><code>\timing</code> コマンドで実行時間を比べると、<code>approximate_row_count</code> 関数が高速なのが分かります。</p>
<pre>=# \timing
タイミングは on です。
=# SELECT count(*) FROM conditions;
  count
---------
 1455480
(1 行)

時間: 246.751 ミリ秒
=# SELECT approximate_row_count('conditions');
 approximate_row_count
-----------------------
               1455840
(1 行)

時間: 4.144 ミリ秒
</pre>
<h2>おわりに</h2>
<p>今回は、TimescaleDB の分析関数として、時間を任意の間隔で丸める <code>time_bucket</code> 関数や、別の列をキーに並び替え、最初、最後の値を取得する <code>first</code>、<code>last</code> 関数を取り上げ、関数の概要や使い方について紹介しました。関数については <a href="https://docs.timescale.com/timescaledb/latest/">TimescaleDB Documentation</a> の <a href="https://docs.timescale.com/api/latest/">API Reference</a> もあわせて参照してください。</p>
<p>次回は、時系列データの自動集計や削除、圧縮の機能について紹介する予定です。</p>
<div>
<a href="https://www.sraoss.co.jp/prod_serv/support/pgsql-mainte/?utm_source=sraoss-techblog&utm_medium=referral&utm_campaign=under-article-pgsql" rel="noopener" style="color:initial;" target="_blank" class="no-ext"></p>
<div style="background-color:#DAEFF6; padding:20px; border-radius:8px; text-align:center;">
SRA OSSでは、PostgreSQL/Pgpool-II のサポートを提供しております。<br />
詳しくは<strong style="color:#2581c4;">弊社ホームページ</strong>をご覧ください。
</div>
<p></a>
</div>

]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>TimescaleDB の紹介</title>
		<link>https://www.sraoss.co.jp/tech-blog/pgsql/timescaledb-intro/</link>
		
		<dc:creator><![CDATA[データベース技術グループ]]></dc:creator>
		<pubDate>Mon, 24 May 2021 04:10:16 +0000</pubDate>
				<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[TimescaleDB]]></category>
		<category><![CDATA[サードパーティーソフトウェア]]></category>
		<guid isPermaLink="false">https://www.sraoss.co.jp/tech-blog/?p=6973</guid>

					<description><![CDATA[TimescaleDB は、IoT 機器のセンサーやスマートメーターが生成するデータのように、時系列に沿って発生するデータを扱うのに適した時系列データベースの機能を、リレーショナルデータベース PostgreSQL に追 ...]]></description>
										<content:encoded><![CDATA[<p>TimescaleDB は、IoT 機器のセンサーやスマートメーターが生成するデータのように、時系列に沿って発生するデータを扱うのに適した時系列データベースの機能を、リレーショナルデータベース PostgreSQL に追加する拡張モジュールです。</p>
<p>この記事では、TimescaleDB の概要とインストール、基本的な使い方について紹介します。</p>
<p><span id="more-6973"></span></p>
<h2>TimescaleDB とは</h2>
<p>TimescaleDB は米国 <a href="https://www.timescale.com/">Timescale 社</a> が開発する時系列データベースで、ソースコードは <a href="https://github.com/timescale/timescaledb">GitHub リポジトリ</a> で公開されています。ライセンスは一部が <a href="https://github.com/timescale/timescaledb/blob/master/tsl/LICENSE-TIMESCALE">Timescale ライセンス (TSL)</a> で、それ以外は <a href="https://github.com/timescale/timescaledb/blob/master/LICENSE-APACHE">Apache ライセンス 2.0</a> です。TSL 部分は簡単に言えばそれ自体をサービスとして提供しない限り自由に使えます。ライセンスについて正確には自分で確認してください。</p>
<p>TimescaleDB は PostgreSQL の拡張モジュールとして実装されていて、リレーショナルデータベースと NoSQL の特長をあわせもちます。</p>
<ul>
<li>使いやすさ &#8211; SQL に完全対応をしていて、PostgreSQL 用のアプリケーションもそのまま接続でき、時系列データ向けの分析や管理機能も備えています。</li>
<li>スケーラビリティの高さ &#8211; データは適切なサイズに分割して格納され、データ量が増えても安定して高速に書き込みでき、並列処理にも対応しています。</li>
<li>信頼性の高さ &#8211; 長い歴史をもつ PostgreSQL 上で動作し、レプリケーションやバックアップなど、PostgreSQL の機能はもちろん、PostgreSQL 用のツールも使えます。</li>
</ul>
<p>TimescaleDB では、データは内部的に時間と空間で分割されたチャンクと呼ばれるテーブルに格納され、ハイパーテーブルを介して透過的にアクセスされます。空間は時間以外にチャンクを分割する条件です。分割方式として <a href="https://www.postgresql.jp/document/current/html/ddl-partitioning.html#DDL-PARTITIONING-IMPLEMENTATION-INHERITANCE">継承によるパーティショニング</a> を採用していて、複数の条件で分割しても階層が多段にならない実装になっています。</p>
<p><img decoding="async" src="https://www.sraoss.co.jp/tech-blog/wp-content/uploads/2021/05/timescaledb-architecture.png" alt="TimescaleDB のアークテクチャ" /></p>
<h2>TimescaleDB のインストール</h2>
<p>TimescaleDB は各プラットフォーム向けのバイナリに加え、Docker イメージや AMI、マネージドサービス Timescale Cloud も提供されています。すべてのインストール方法については <a href="https://docs.timescale.com/latest/main">TimescaleDB Documentation</a> の <a href="https://docs.timescale.com/latest/getting-started/installation">Installation</a> を参照してください。</p>
<p>TimescaleDB は 2021 年 6 月時点で以下のバージョンがメンテナンスされていて、それぞれ対応する PostgreSQL のバージョンが異なります。</p>
<table>
<thead>
<tr>
<th>TimescaleDB バージョン</th>
<th>対応 PostgreSQL バージョン</th>
</tr>
</thead>
<tbody>
<tr>
<td>2.4以降</td>
<td>12、13</td>
</tr>
<tr>
<td>2.1～2.3</td>
<td>12、13</td>
</tr>
<tr>
<td>2.0</td>
<td>11、12</td>
</tr>
<tr>
<td>1.7</td>
<td>9.6、10、11、12</td>
</tr>
</tbody>
</table>
<p>ここでは、CentOS 8 上の PostgreSQL 13 に Yum を使って TimescaleDB をインストールしていきます。</p>
<ol>
<li>TimescaleDB の Yum リポジトリを登録します。
<pre>$ sudo tee /etc/yum.repos.d/timescale_timescaledb.repo &lt;&lt;EOF
[timescale_timescaledb]
name=timescale_timescaledb
baseurl=https://packagecloud.io/timescale/timescaledb/el/\$releasever/\$basearch
repo_gpgcheck=1
gpgcheck=0
enabled=1
gpgkey=https://packagecloud.io/timescale/timescaledb/gpgkey
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
metadata_expire=300
EOF
</pre>
</li>
<li>TimescaleDB の RPM パッケージをインストールします。
<pre>$ sudo yum -y install timescaledb-2-postgresql-13
(省略)
Installed:
  timescaledb-2-postgresql-13.x86_64 0:2.2.0-0.el8

Dependency Installed:
  timescaledb-2-loader-postgresql-13.x86_64 0:2.2.0-0.el8
  timescaledb-tools.x86_64 0:0.11.0-0.el8

Complete!
</pre>
</li>
<li>TimescaleDB 向けに PostgreSQL の設定を行います。設定ファイル <code>postgresql.conf</code> を直接編集してもよいですが、ここでは、メモリ量や CPU 数をもとに対話的に設定を行う <code>timescaledb-tune</code> コマンドを使います。
<pre>$ sudo timescaledb-tune --pg-config=/usr/pgsql-13/bin/pg_config
Using postgresql.conf at this path:
/var/lib/pgsql/13/data/postgresql.conf

Is this correct? [(y)es/(n)o]: y
Writing backup to:
/tmp/timescaledb_tune.backup202105010056

shared_preload_libraries needs to be updated
Current:
#shared_preload_libraries = ''
Recommended:
shared_preload_libraries = 'timescaledb'
Is this okay? [(y)es/(n)o]: y
success: shared_preload_libraries will be updated

Tune memory/parallelism/WAL and other settings? [(y)es/(n)o]: y
Recommendations based on 465.21 MB of available memory and 1 CPUs for PostgreSQL 13

Memory settings recommendations
Current:
shared_buffers = 128MB
#effective_cache_size = 4GB
#maintenance_work_mem = 64MB
#work_mem = 4MB
Recommended:
shared_buffers = 119094kB
effective_cache_size = 357282kB
maintenance_work_mem = 59547kB
work_mem = 2977kB
Is this okay? [(y)es/(s)kip/(q)uit]: y
success: memory settings will be updated

WAL settings recommendations
Current:
#wal_buffers = -1
min_wal_size = 80MB
Recommended:
wal_buffers = 3572kB
min_wal_size = 512MB
Is this okay? [(y)es/(s)kip/(q)uit]: y
success: WAL settings will be updated

Miscellaneous settings recommendations
Current:
#default_statistics_target = 100
#random_page_cost = 4.0
#checkpoint_completion_target = 0.5
max_connections = 100
#max_locks_per_transaction = 64
#autovacuum_max_workers = 3
#autovacuum_naptime = 1min
#effective_io_concurrency = 1
Recommended:
default_statistics_target = 500
random_page_cost = 1.1
checkpoint_completion_target = 0.9
max_connections = 20
max_locks_per_transaction = 64
autovacuum_max_workers = 10
autovacuum_naptime = 10
effective_io_concurrency = 200
Is this okay? [(y)es/(s)kip/(q)uit]: y
success: miscellaneous settings will be updated
Saving changes to: /var/lib/pgsql/13/data/postgresql.conf
</pre>
<p><code>--pg-config</code> オプションには <code>pg_config</code> コマンドのパスを指定します。そのほかのオプションは <code>--help</code> オプションで確認できます。実行を開始すると、次々に聞かれる質問に答えていきます。基本的には <code>y</code> を入力していけばよいです。最後に設定がファイルに書き込まれます。</li>
<li>設定を反映するため、PostgreSQL のサービスを再起動します。
<pre>$ sudo systemctl restart postgresql-13
</pre>
</li>
<li>TimescaleDB の拡張モジュールをデータベースにインストールします。ここでは、PostgreSQL のスーパーユーザ <code>postgres</code> に切り替わり、テスト用に <code>test</code> データベースを作成し、そこにインストールします。
<pre>$ sudo su - postgres
$ createdb test
$ psql -c "CREATE EXTENSION timescaledb" test
WARNING:
WELCOME TO
 _____ _                               _     ____________
|_   _(_)                             | |    |  _  \ ___ \
  | |  _ _ __ ___   ___  ___  ___ __ _| | ___| | | | |_/ /
  | | | |  _ ` _ \ / _ \/ __|/ __/ _` | |/ _ \ | | | ___ \
  | | | | | | | | |  __/\__ \ (_| (_| | |  __/ |/ /| |_/ /
  |_| |_|_| |_| |_|\___||___/\___\__,_|_|\___|___/ \____/
               Running version 2.2.0
For more information on TimescaleDB, please visit the following links:

 1. Getting started: https://docs.timescale.com/getting-started
 2. API reference documentation: https://docs.timescale.com/api
 3. How TimescaleDB is designed: https://docs.timescale.com/introduction/architecture

Note: TimescaleDB collects anonymous reports to better understand and assist our users.
For more information and how to disable, please see our docs https://docs.timescaledb.com/using-timescaledb/telemetry.

CREATE EXTENSION
</pre>
</li>
</ol>
<h2>TimescaleDB の基本的な使い方</h2>
<p>ここからは、<code>test</code> データベースに接続し、TimescaleDB の基本的な使い方を確認していきます。</p>
<pre>$ psql test
psql (13.2)
"help"でヘルプを表示します。

=#
</pre>
<h3>ハイパーテーブルの作成</h3>
<p>ハイパーテーブルを作成するには通常のテーブルを作成し、<code>create_hypertable</code> 関数を実行します。ここでは、時間と場所ごとに温度と湿度を格納する <code>conditions</code> テーブルを作成し、ハイパーテーブルに変換します。</p>
<pre>=# CREATE TABLE conditions (
     time timestamp NOT NULL,
     location text NOT NULL,
     temperature double precision,
     humidity double precision
   );
CREATE TABLE
=# SELECT create_hypertable('conditions', 'time');
    create_hypertable
-------------------------
 (1,public,conditions,t)
(1 行)
</pre>
<p><code>create_hypertable</code> 関数の引数にはハイパーテーブルに変換するテーブル名、分割の条件にする時間の列名を指定します。戻り値はそれぞれハイパーテーブルの ID、スキーマ名、テーブル名、実際に作成されたかが返されます。</p>
<p>チャンクはデフォルトで 7 日ごとに分割されます。時間列のデータ型はタイムスタンプや日付以外に整数にも対応しています。整数の場合には値が表す時間の大きさが分からないため、チャンクを分割する間隔を <code>chunk_time_interval</code> 引数で指定する必要があります。例えば、時間列が秒を表し、7 日ごとに分割する場合には、7 日 × 24 時間 × 60 分 × 60 秒 = 604,800 を指定します。</p>
<pre>(以下、例示のため、実行不要)
=# SELECT create_hypertable('conditions', 'time');
ERROR:  integer dimensions require an explicit interval
=# SELECT create_hypertable('conditions', 'time', chunk_time_interval := 604800);
    create_hypertable
-------------------------
 (1,public,conditions,t)
(1 行)
</pre>
<p>変換元のテーブルは空でないとエラーになります。<code>migrate_data</code> 引数に <code>true</code> を指定すれば、データを移行することもできます。データ量が多いと時間がかかり、外部キー制約があるとデッドロックが発生する可能性があります。通常はハイパーテーブルの作成後にデータを投入したほうがよいでしょう。</p>
<pre>(以下、例示のため、実行不要)
=# SELECT create_hypertable('conditions', 'time');
ERROR:  table "conditions" is not empty
HINT:  You can migrate data by specifying 'migrate_data =&gt; true' when calling this function.
=# SELECT create_hypertable('conditions', 'time', migrate_data := true);
NOTICE:  migrating data to chunks
DETAIL:  Migration might take a while depending on the amount of data.
    create_hypertable
-------------------------
 (1,public,conditions,t)
(1 行)
</pre>
<p><code>create_hypertable</code> 関数について詳しくは TimescaleDB Documentation の <a href="https://docs.timescale.com/latest/api#create_hypertable">API Reference</a> を参照してください。</p>
<h3>時系列データの操作</h3>
<p>時系列データの操作はハイパーテーブルを介して通常のデータと同じようにできます。ここでは、まず、データの挿入、検索、更新、削除をしてみます。</p>
<pre>=# INSERT INTO conditions
     VALUES ('2021-05-01 09:00:00', 'tokyo', 19.4, 62.0);
INSERT 0 1
=# SELECT * FROM conditions;
        time         | location | temperature | humidity
---------------------+----------+-------------+----------
 2021-05-01 09:00:00 | tokyo    |        19.4 |       62
(1 行)

=# UPDATE conditions
   SET temperature = temperature + 0.1
   WHERE time = '2021-05-01 09:00:00'
     AND location = 'tokyo';
UPDATE 1
=# DELETE FROM conditions
   WHERE time = '2021-05-01 09:00:00'
     AND location = 'tokyo';
DELETE 1
</pre>
<p>次に、あとで分析に使うデータを生成します。データは 2020 年 1 月 1 日から 1 分間隔で 1 年間、場所は東京、名古屋、大阪の 3 か所、温度は 10 〜 30 度、湿度は 60 〜 90% の範囲でランダムです。これで 55 個のチャンクからなる 1,581,120 行、135MB のデータになります。データの投入後は <code>ANALYZE</code> コマンドで統計情報を更新しておきましょう。</p>
<pre>=# INSERT INTO conditions
   SELECT time,
     location,
     round(10 + random()::numeric * (30 - 10), 1) AS temperature,
     round(60 + random()::numeric * (90 - 60), 0) AS humidity
   FROM generate_series('2020-01-01 00:00:00'::timestamp, '2020-12-31 23:59:00', '1 minute') AS time,
     unnest(ARRAY['tokyo', 'nagoya', 'osaka']) AS location;
INSERT 0 1581120
=# ANALYZE;
ANALYZE
</pre>
<h3>チャンクの削除</h3>
<p>データの削除は <code>DELETE</code> コマンドでもできますが、それだと不要領域が発生し、回収して再利用可能にするにはバキュームが必要です。それに対して、チャンクごと削除すれば、不要領域が発生せずに済みます。</p>
<p>チャンクを削除するには <code>drop_chunks</code>関数を実行します。ここでは、2021 年 2 月 1 より前のチャンクを削除します。</p>
<pre>=# SELECT drop_chunks('conditions', '2020-02-01 00:00:00'::timestamp);
              drop_chunks
----------------------------------------
 _timescaledb_internal._hyper_1_2_chunk
 _timescaledb_internal._hyper_1_3_chunk
 _timescaledb_internal._hyper_1_4_chunk
 _timescaledb_internal._hyper_1_5_chunk
 _timescaledb_internal._hyper_1_6_chunk
(5 行)
</pre>
<p><code>drop_chunks</code> 関数の引数にはハイパーテーブルの名前、いつより前のデータしか含まないチャンクを削除するかのタイムスタンプを指定します。戻り値は削除されたチャンクの名前が返されます。</p>
<p>いつより前を削除するかはタイムスタンプや日付、整数以外に間隔にも対応しています。間隔の場合には現在を基準にその間隔より前が削除されます。例えば、現在が 2021 年 5 月 1 日で、間隔が 15 か月の場合には、2020 年 2 月 1 日より前のチャンクが削除されます。</p>
<pre>(以下、例示のため、実行不要)
=# SELECT drop_chunks('conditions', '15 months'::interval);
              drop_chunks
----------------------------------------
 _timescaledb_internal._hyper_1_2_chunk
 _timescaledb_internal._hyper_1_3_chunk
 _timescaledb_internal._hyper_1_4_chunk
 _timescaledb_internal._hyper_1_5_chunk
 _timescaledb_internal._hyper_1_6_chunk
(5 行)
</pre>
<p><code>drop_chunks</code> 関数について詳しくは TimescaleDB Documentation の <a href="https://docs.timescale.com/latest/api#drop_chunks">API Reference</a> を参照してください。</p>
<h2>おわりに</h2>
<p>今回は、リレーショナルデータベースと NoSQL の特長をあわせもった時系列データベース TimescaleDB の概要、CentOS 8 上の PostgreSQL 13 への Yum を使ったインストール、ハイパーテーブルの作成や時系列データの操作など、基本的な使い方について紹介しました。</p>
<p>次回は、TimescaleDB の備える時系列データ向けの分析機能について紹介します。</p>
<div>
<a href="https://www.sraoss.co.jp/prod_serv/support/pgsql-mainte/?utm_source=sraoss-techblog&utm_medium=referral&utm_campaign=under-article-pgsql" rel="noopener" style="color:initial;" target="_blank" class="no-ext"></p>
<div style="background-color:#DAEFF6; padding:20px; border-radius:8px; text-align:center;">
SRA OSSでは、PostgreSQL/Pgpool-II のサポートを提供しております。<br />
詳しくは<strong style="color:#2581c4;">弊社ホームページ</strong>をご覧ください。
</div>
<p></a>
</div>

]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
