{
"cells": [
{
"cell_type": "markdown",
"id": "7f1f5a4a-ae34-4a27-9efa-399edc0e384a",
"metadata": {
"tags": []
},
"source": [
"## Benchmark: ClickHouse Vs. InfluxDB Vs. Postgresql Vs. Parquet \n",
"\n",
"-----\n",
"\n",
"#### How to use:\n",
"* Rename the file \"properties-model.ini\" to \"properties.ini\"\n",
"* Fill with your own credentials\n",
"----\n",
"\n",
"The proposal of this work is to compare the speed in read/writing a midle level of data ( a dataset with 9 columns and 50.000 lines) to four diferent databases:\n",
"* ClickHouse\n",
"* InfluxDB\n",
"* Postgresql\n",
"* Parquet (in a S3 Minio Storage)
\n",
"ToDo:
\n",
"* DuckDB with Polars\n",
"* MongoDB\n",
"* Kdb+\n",
"\n",
" \n",
"Deve-se relevar:\n",
"é uma \"cold-storage\" ou \"frezze-storage\"?
\n",
"influxdb: alta leitura e possui a vantagem da indexaçõa para vizualização de dados em gráficos.\n",
"\n",
"notas: \n",
"* comparar tamanho do csv com parquet"
]
},
{
"cell_type": "markdown",
"id": "6bb26ce7-1e84-4665-accd-916bb977f95d",
"metadata": {
"tags": []
},
"source": [
"### Imports "
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "ab6c6c81-6ac1-4668-a79b-a9a0341fb35a",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"False"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import configparser\n",
"import time\n",
"import timeit\n",
"from datetime import datetime\n",
"\n",
"import duckdb\n",
"import influxdb_client\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import pandas as pd\n",
"\n",
"# import pymongo\n",
"from clickhouse_driver import Client\n",
"from dotenv import load_dotenv\n",
"from minio import Minio\n",
"from pymongo import MongoClient\n",
"from pytz import timezone\n",
"from sqlalchemy import create_engine\n",
"\n",
"load_dotenv()"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "55c3cd57-0996-4723-beb5-8f3196c96009",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"# Variables\n",
"dbname = \"EURUSDtest\""
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "968403e3-2e5e-4834-b969-be4600e2963a",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"arq = configparser.RawConfigParser()\n",
"arq.read(\"properties.ini\")\n",
"ClickHouseUser = arq.get(\"CLICKHOUSE\", \"user\")\n",
"ClickHouseKey = arq.get(\"CLICKHOUSE\", \"key\")\n",
"ClickHouseUrl = arq.get(\"CLICKHOUSE\", \"url\")\n",
"\n",
"InfluxDBUser = arq.get(\"INFLUXDB\", \"user\")\n",
"InfluxDBKey = arq.get(\"INFLUXDB\", \"key\")\n",
"InfluxDBUrl = arq.get(\"INFLUXDB\", \"url\")\n",
"InfluxDBBucket = arq.get(\"INFLUXDB\", \"bucket\")\n",
"\n",
"PostgresqlUser = arq.get(\"POSTGRESQL\", \"user\")\n",
"PostgresqlKey = arq.get(\"POSTGRESQL\", \"key\")\n",
"PostgresqlUrl = arq.get(\"POSTGRESQL\", \"url\")\n",
"PostgresqlDB = arq.get(\"POSTGRESQL\", \"database\")\n",
"\n",
"S3MinioUser = arq.get(\"S3MINIO\", \"user\")\n",
"S3MinioKey = arq.get(\"S3MINIO\", \"key\")\n",
"S3MinioUrl = arq.get(\"S3MINIO\", \"url\")\n",
"S3MinioRegion = arq.get(\"S3MINIO\", \"region\")\n",
"\n",
"MongoUser = arq.get(\"MONGODB\", \"user\")\n",
"MongoKey = arq.get(\"MONGODB\", \"key\")\n",
"MongoUrl = arq.get(\"MONGODB\", \"url\")"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "3634a4ec-04c2-4f1e-8659-5d22eb17a254",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" id | \n",
" from | \n",
" at | \n",
" to | \n",
" open | \n",
" close | \n",
" min | \n",
" max | \n",
" volume | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" 7730801 | \n",
" 2023-01-02 15:58:45 | \n",
" 1672675140000000000 | \n",
" 2023-01-02 15:59:00 | \n",
" 1.065995 | \n",
" 1.066035 | \n",
" 1.065930 | \n",
" 1.066070 | \n",
" 57 | \n",
"
\n",
" \n",
" | 1 | \n",
" 7730802 | \n",
" 2023-01-02 15:59:00 | \n",
" 1672675155000000000 | \n",
" 2023-01-02 15:59:15 | \n",
" 1.066055 | \n",
" 1.066085 | \n",
" 1.066005 | \n",
" 1.066115 | \n",
" 52 | \n",
"
\n",
" \n",
" | 2 | \n",
" 7730803 | \n",
" 2023-01-02 15:59:15 | \n",
" 1672675170000000000 | \n",
" 2023-01-02 15:59:30 | \n",
" 1.066080 | \n",
" 1.066025 | \n",
" 1.066025 | \n",
" 1.066110 | \n",
" 57 | \n",
"
\n",
" \n",
" | 3 | \n",
" 7730804 | \n",
" 2023-01-02 15:59:30 | \n",
" 1672675185000000000 | \n",
" 2023-01-02 15:59:45 | \n",
" 1.065980 | \n",
" 1.065985 | \n",
" 1.065885 | \n",
" 1.066045 | \n",
" 64 | \n",
"
\n",
" \n",
" | 4 | \n",
" 7730805 | \n",
" 2023-01-02 15:59:45 | \n",
" 1672675200000000000 | \n",
" 2023-01-02 16:00:00 | \n",
" 1.065975 | \n",
" 1.066055 | \n",
" 1.065830 | \n",
" 1.066055 | \n",
" 50 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" id from at to \\\n",
"0 7730801 2023-01-02 15:58:45 1672675140000000000 2023-01-02 15:59:00 \n",
"1 7730802 2023-01-02 15:59:00 1672675155000000000 2023-01-02 15:59:15 \n",
"2 7730803 2023-01-02 15:59:15 1672675170000000000 2023-01-02 15:59:30 \n",
"3 7730804 2023-01-02 15:59:30 1672675185000000000 2023-01-02 15:59:45 \n",
"4 7730805 2023-01-02 15:59:45 1672675200000000000 2023-01-02 16:00:00 \n",
"\n",
" open close min max volume \n",
"0 1.065995 1.066035 1.065930 1.066070 57 \n",
"1 1.066055 1.066085 1.066005 1.066115 52 \n",
"2 1.066080 1.066025 1.066025 1.066110 57 \n",
"3 1.065980 1.065985 1.065885 1.066045 64 \n",
"4 1.065975 1.066055 1.065830 1.066055 50 "
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# %%time\n",
"# Load Dataset\n",
"df = pd.read_csv(\"out.csv\", index_col=0)\n",
"df.head()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "76199f91-31d6-416b-9f15-5d435b3792c9",
"metadata": {},
"outputs": [],
"source": [
"df[\"from\"] = pd.to_datetime(df[\"from\"], unit=\"s\")\n",
"df[\"to\"] = pd.to_datetime(df[\"to\"], unit=\"s\")\n",
"# Optional use when not transoformed yet\n",
"# Transform Datetime"
]
},
{
"cell_type": "markdown",
"id": "274cc026-2f48-4e38-b80f-b1a9ff982060",
"metadata": {
"tags": []
},
"source": [
"#### Funçoes\n",
"\n",
"-> Class"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "27de1ec8-4de1-440a-b555-b4a46c5ef7ce",
"metadata": {},
"outputs": [],
"source": [
"def timestamp2dataHora(x, timezone_=\"America/Sao_Paulo\"):\n",
" d = datetime.fromtimestamp(x, tz=timezone(timezone_))\n",
" return d"
]
},
{
"cell_type": "markdown",
"id": "4a8d5703-9bc9-4d38-83ff-457159304d58",
"metadata": {
"tags": []
},
"source": [
"### ClickHouse"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "c3202bbb-2655-45b2-b166-9f45a3ef854c",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Failed to connect to 192.168.1.142:9000\n",
"Traceback (most recent call last):\n",
" File \"/home/sandman/dev/pipenv/lib/python3.10/site-packages/clickhouse_driver/connection.py\", line 395, in connect\n",
" return self._init_connection(host, port)\n",
" File \"/home/sandman/dev/pipenv/lib/python3.10/site-packages/clickhouse_driver/connection.py\", line 325, in _init_connection\n",
" self.socket = self._create_socket(host, port)\n",
" File \"/home/sandman/dev/pipenv/lib/python3.10/site-packages/clickhouse_driver/connection.py\", line 297, in _create_socket\n",
" raise err\n",
" File \"/home/sandman/dev/pipenv/lib/python3.10/site-packages/clickhouse_driver/connection.py\", line 288, in _create_socket\n",
" sock.connect(sa)\n",
"TimeoutError: timed out\n"
]
},
{
"ename": "SocketTimeoutError",
"evalue": "Code: 209. (192.168.1.142:9000)",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mSocketTimeoutError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[0;32mIn[15], line 44\u001b[0m\n\u001b[1;32m 40\u001b[0m client\u001b[38;5;241m.\u001b[39mdisconnect()\n\u001b[1;32m 41\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m dfQuery\n\u001b[0;32m---> 44\u001b[0m \u001b[43mcHouseCreateDb\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdbname\u001b[49m\u001b[43m)\u001b[49m\n",
"Cell \u001b[0;32mIn[15], line 17\u001b[0m, in \u001b[0;36mcHouseCreateDb\u001b[0;34m(databasename)\u001b[0m\n\u001b[1;32m 15\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mcHouseCreateDb\u001b[39m(databasename):\n\u001b[1;32m 16\u001b[0m client \u001b[38;5;241m=\u001b[39m cHouseConnect()\n\u001b[0;32m---> 17\u001b[0m \u001b[43mclient\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mexecute\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 18\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mCREATE TABLE IF NOT EXISTS \u001b[39;49m\u001b[38;5;132;43;01m{}\u001b[39;49;00m\u001b[38;5;124;43m (id UInt32,\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\n\u001b[1;32m 19\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mfrom DateTime, at UInt64, to DateTime, open Float64,\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\n\u001b[1;32m 20\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mclose Float64, min Float64, max Float64, volume UInt32)\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\n\u001b[1;32m 21\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mENGINE MergeTree ORDER BY to\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mformat\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdatabasename\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 22\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 23\u001b[0m client\u001b[38;5;241m.\u001b[39mdisconnect()\n\u001b[1;32m 24\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mDatabase created\u001b[39m\u001b[38;5;124m\"\u001b[39m\n",
"File \u001b[0;32m~/dev/pipenv/lib/python3.10/site-packages/clickhouse_driver/client.py:361\u001b[0m, in \u001b[0;36mClient.execute\u001b[0;34m(self, query, params, with_column_types, external_tables, query_id, settings, types_check, columnar)\u001b[0m\n\u001b[1;32m 318\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 319\u001b[0m \u001b[38;5;124;03mExecutes query.\u001b[39;00m\n\u001b[1;32m 320\u001b[0m \n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 356\u001b[0m \u001b[38;5;124;03m and types.\u001b[39;00m\n\u001b[1;32m 357\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 359\u001b[0m start_time \u001b[38;5;241m=\u001b[39m time()\n\u001b[0;32m--> 361\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdisconnect_on_error(query, settings):\n\u001b[1;32m 362\u001b[0m \u001b[38;5;66;03m# INSERT queries can use list/tuple/generator of list/tuples/dicts.\u001b[39;00m\n\u001b[1;32m 363\u001b[0m \u001b[38;5;66;03m# For SELECT parameters can be passed in only in dict right now.\u001b[39;00m\n\u001b[1;32m 364\u001b[0m is_insert \u001b[38;5;241m=\u001b[39m \u001b[38;5;28misinstance\u001b[39m(params, (\u001b[38;5;28mlist\u001b[39m, \u001b[38;5;28mtuple\u001b[39m, types\u001b[38;5;241m.\u001b[39mGeneratorType))\n\u001b[1;32m 366\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m is_insert:\n",
"File \u001b[0;32m~/dev/anaconda3/lib/python3.10/contextlib.py:135\u001b[0m, in \u001b[0;36m_GeneratorContextManager.__enter__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 133\u001b[0m \u001b[38;5;28;01mdel\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39margs, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mkwds, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfunc\n\u001b[1;32m 134\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 135\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mnext\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgen\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 136\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mStopIteration\u001b[39;00m:\n\u001b[1;32m 137\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mRuntimeError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mgenerator didn\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mt yield\u001b[39m\u001b[38;5;124m\"\u001b[39m) \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n",
"File \u001b[0;32m~/dev/pipenv/lib/python3.10/site-packages/clickhouse_driver/client.py:305\u001b[0m, in \u001b[0;36mClient.disconnect_on_error\u001b[0;34m(self, query, settings)\u001b[0m\n\u001b[1;32m 302\u001b[0m \u001b[38;5;129m@contextmanager\u001b[39m\n\u001b[1;32m 303\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mdisconnect_on_error\u001b[39m(\u001b[38;5;28mself\u001b[39m, query, settings):\n\u001b[1;32m 304\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 305\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mestablish_connection\u001b[49m\u001b[43m(\u001b[49m\u001b[43msettings\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 307\u001b[0m \u001b[38;5;28;01myield\u001b[39;00m\n\u001b[1;32m 309\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtrack_current_database(query)\n",
"File \u001b[0;32m~/dev/pipenv/lib/python3.10/site-packages/clickhouse_driver/client.py:292\u001b[0m, in \u001b[0;36mClient.establish_connection\u001b[0;34m(self, settings)\u001b[0m\n\u001b[1;32m 290\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mconnection \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mget_connection()\n\u001b[1;32m 291\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mmake_query_settings(settings)\n\u001b[0;32m--> 292\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mconnection\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mforce_connect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 293\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlast_query \u001b[38;5;241m=\u001b[39m QueryInfo()\n\u001b[1;32m 295\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (errors\u001b[38;5;241m.\u001b[39mSocketTimeoutError, errors\u001b[38;5;241m.\u001b[39mNetworkError):\n",
"File \u001b[0;32m~/dev/pipenv/lib/python3.10/site-packages/clickhouse_driver/connection.py:254\u001b[0m, in \u001b[0;36mConnection.force_connect\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 251\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcheck_query_execution()\n\u001b[1;32m 253\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mconnected:\n\u001b[0;32m--> 254\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 256\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mping():\n\u001b[1;32m 257\u001b[0m logger\u001b[38;5;241m.\u001b[39mwarning(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mConnection was closed, reconnecting.\u001b[39m\u001b[38;5;124m'\u001b[39m)\n",
"File \u001b[0;32m~/dev/pipenv/lib/python3.10/site-packages/clickhouse_driver/connection.py:416\u001b[0m, in \u001b[0;36mConnection.connect\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 413\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhosts\u001b[38;5;241m.\u001b[39mrotate(\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m)\n\u001b[1;32m 415\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m err \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m--> 416\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m err\n",
"\u001b[0;31mSocketTimeoutError\u001b[0m: Code: 209. (192.168.1.142:9000)"
]
}
],
"source": [
"# !! driver tcp.\n",
"def cHouseConnect():\n",
" client = Client(\n",
" host=ClickHouseUrl,\n",
" user=ClickHouseUser,\n",
" password=ClickHouseKey,\n",
" settings={\"use_numpy\": True},\n",
" )\n",
" return client\n",
"\n",
"\n",
"# Create Tables in ClickHouse\n",
"# !! ALTERAR TIPOS !!\n",
"# ENGINE: 'Memory' desaparece quando server é reiniciado\n",
"def cHouseCreateDb(databasename):\n",
" client = cHouseConnect()\n",
" client.execute(\n",
" \"CREATE TABLE IF NOT EXISTS {} (id UInt32,\"\n",
" \"from DateTime, at UInt64, to DateTime, open Float64,\"\n",
" \"close Float64, min Float64, max Float64, volume UInt32)\"\n",
" \"ENGINE MergeTree ORDER BY to\".format(databasename)\n",
" )\n",
" client.disconnect()\n",
" return \"Database created\"\n",
"\n",
"\n",
"# Write dataframe to db\n",
"def cHouseInsertDf(dbName, dataframe):\n",
" client = cHouseConnect()\n",
" client.insert_dataframe(\"INSERT INTO {} VALUES\".format(dbName), dataframe)\n",
" client.disconnect()\n",
" return \" dataframe {} inserted in clickhouse database\".format(dataframe)\n",
"\n",
"\n",
"def cHouseQueryDf(databaseName):\n",
" client = cHouseConnect()\n",
" dfQuery = client.query_dataframe(\n",
" \"SELECT * FROM default.{}\".format(databaseName)\n",
" ) # LIMIT 10000\n",
" client.disconnect()\n",
" return dfQuery\n",
"\n",
"\n",
"cHouseCreateDb(dbname)"
]
},
{
"cell_type": "code",
"execution_count": 47,
"id": "cc4865b3-a1bc-4a35-9624-15334754b3a1",
"metadata": {},
"outputs": [],
"source": [
"# Insert to db and benchmark time\n",
"start = timeit.default_timer()\n",
"cHouseInsertDf(dbname, df)\n",
"stop = timeit.default_timer()\n",
"cHouse_write_execution_time = stop - start"
]
},
{
"cell_type": "code",
"execution_count": 48,
"id": "1fac82c1-2d04-44ef-893a-dc13b755e6d8",
"metadata": {},
"outputs": [],
"source": [
"# read from db and benchmark time\n",
"start = timeit.default_timer()\n",
"dfCh = cHouseQueryDf(dbname)\n",
"stop = timeit.default_timer()\n",
"cHouse_read_execution_time = stop - start"
]
},
{
"cell_type": "code",
"execution_count": 49,
"id": "597ae7bd-2eea-44d7-b379-f0eb7e745c15",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" id | \n",
" from | \n",
" at | \n",
" to | \n",
" open | \n",
" close | \n",
" min | \n",
" max | \n",
" volume | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" 7730801 | \n",
" 2023-01-02 15:58:45 | \n",
" 1672675140000000000 | \n",
" 2023-01-02 15:59:00 | \n",
" 1.065995 | \n",
" 1.066035 | \n",
" 1.065930 | \n",
" 1.066070 | \n",
" 57 | \n",
"
\n",
" \n",
" | 1 | \n",
" 7730801 | \n",
" 2023-01-02 15:58:45 | \n",
" 1672675140000000000 | \n",
" 2023-01-02 15:59:00 | \n",
" 1.065995 | \n",
" 1.066035 | \n",
" 1.065930 | \n",
" 1.066070 | \n",
" 57 | \n",
"
\n",
" \n",
" | 2 | \n",
" 7730802 | \n",
" 2023-01-02 15:59:00 | \n",
" 1672675155000000000 | \n",
" 2023-01-02 15:59:15 | \n",
" 1.066055 | \n",
" 1.066085 | \n",
" 1.066005 | \n",
" 1.066115 | \n",
" 52 | \n",
"
\n",
" \n",
" | 3 | \n",
" 7730802 | \n",
" 2023-01-02 15:59:00 | \n",
" 1672675155000000000 | \n",
" 2023-01-02 15:59:15 | \n",
" 1.066055 | \n",
" 1.066085 | \n",
" 1.066005 | \n",
" 1.066115 | \n",
" 52 | \n",
"
\n",
" \n",
" | 4 | \n",
" 7730803 | \n",
" 2023-01-02 15:59:15 | \n",
" 1672675170000000000 | \n",
" 2023-01-02 15:59:30 | \n",
" 1.066080 | \n",
" 1.066025 | \n",
" 1.066025 | \n",
" 1.066110 | \n",
" 57 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" id from at to \\\n",
"0 7730801 2023-01-02 15:58:45 1672675140000000000 2023-01-02 15:59:00 \n",
"1 7730801 2023-01-02 15:58:45 1672675140000000000 2023-01-02 15:59:00 \n",
"2 7730802 2023-01-02 15:59:00 1672675155000000000 2023-01-02 15:59:15 \n",
"3 7730802 2023-01-02 15:59:00 1672675155000000000 2023-01-02 15:59:15 \n",
"4 7730803 2023-01-02 15:59:15 1672675170000000000 2023-01-02 15:59:30 \n",
"\n",
" open close min max volume \n",
"0 1.065995 1.066035 1.065930 1.066070 57 \n",
"1 1.065995 1.066035 1.065930 1.066070 57 \n",
"2 1.066055 1.066085 1.066005 1.066115 52 \n",
"3 1.066055 1.066085 1.066005 1.066115 52 \n",
"4 1.066080 1.066025 1.066025 1.066110 57 "
]
},
"execution_count": 49,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dfCh.head()"
]
},
{
"cell_type": "code",
"execution_count": 50,
"id": "86794e47-611f-4ca8-a7e8-07e71afafe67",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"5.175396532999002\n"
]
}
],
"source": [
"print(cHouse_read_execution_time)"
]
},
{
"cell_type": "code",
"execution_count": 51,
"id": "e7926062-8e84-4d3f-90a9-32807ce4f3d4",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"6.163630739996734\n"
]
}
],
"source": [
"print(cHouse_write_execution_time)"
]
},
{
"cell_type": "code",
"execution_count": 52,
"id": "8faa5683-a204-461d-80c3-67644aa714ce",
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 1.15 s, sys: 216 ms, total: 1.36 s\n",
"Wall time: 5.24 s\n"
]
}
],
"source": [
"%%time\n",
"dfCh = cHouseQueryDf(dbname)"
]
},
{
"cell_type": "markdown",
"id": "1d389546-911f-43f7-aad1-49f7bcc83503",
"metadata": {
"jp-MarkdownHeadingCollapsed": true,
"tags": []
},
"source": [
"### InfluxDB\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c3e7ebfd-76f1-4ac4-9833-312eb1a531af",
"metadata": {},
"outputs": [],
"source": [
"client = influxdb_client.InfluxDBClient(\n",
" url=InfluxDBUrl, token=InfluxDBKey, org=InfluxDBUser\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cbf61f12-830b-4c57-804a-2257d8b3599a",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"# Read data from CSV without index and parse 'TimeStamp' as date.\n",
"df = pd.read_csv(\"out.csv\", sep=\",\", index_col=False, parse_dates=[\"from\"])\n",
"# Set 'TimeStamp' field as index of dataframe # test another indexs\n",
"df.set_index(\"from\", inplace=True)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "54342a28-ba2b-4ade-a692-00566b53a639",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"df.head()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f861fab2-f1b1-49dd-b758-12d10aef3462",
"metadata": {},
"outputs": [],
"source": [
"%%time\n",
"# gravando... demorou... mas deu certo\n",
"with client.write_api() as writer:\n",
" writer.write(\n",
" bucket=InfluxDBBucket,\n",
" record=df,\n",
" data_frame_measurement_name=\"id\",\n",
" data_frame_tag_columns=[\"volume\"],\n",
" )"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0bb2563d-68e2-4ff4-8842-70ac730dc6b1",
"metadata": {},
"outputs": [],
"source": [
"# data\n",
"# |> pivot(\n",
"# rowKey:[\"_time\"],\n",
"# columnKey: [\"_field\"],\n",
"# valueColumn: \"_value\"\n",
"# )"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bb1596f9-4cee-4642-803a-ee61c9dddf64",
"metadata": {},
"outputs": [],
"source": [
"# Read"
]
},
{
"cell_type": "markdown",
"id": "b9ddfdc6-c899-4f6c-9b4e-8ec6ab6d7e05",
"metadata": {
"tags": []
},
"source": [
"### Postgresql"
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "16cd8eb7-333d-43fd-88e0-ee983645d3fd",
"metadata": {},
"outputs": [
{
"ename": "SyntaxError",
"evalue": "invalid syntax. Perhaps you forgot a comma? (1520588424.py, line 4)",
"output_type": "error",
"traceback": [
"\u001b[0;36m Cell \u001b[0;32mIn[23], line 4\u001b[0;36m\u001b[0m\n\u001b[0;31m \"postgresql+psycopg2://{}:{}@{}:5432/{}\".format(\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax. Perhaps you forgot a comma?\n"
]
}
],
"source": [
"# Connect / Create Tables\n",
"def psqlConnect():\n",
" engine = create_engine(\n",
" \"postgresql+psycopg2://{}:{}@{}:5432/{}\".format(\n",
" PostgresqlUser, PostgresqlKey, PostgresqlUrl, PostgresqlDB\n",
" )\n",
" )\n",
" return engine\n",
"\n",
"\n",
"psqlConnect()\n",
"# testar função"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e173a45b-60a1-4c33-946e-ccf98bf8e97f",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 26,
"id": "be31f3a0-b7ed-48e6-9b65-dc16319fb8d1",
"metadata": {},
"outputs": [],
"source": [
"# Drop old table and create new empty table\n",
"def psqlCreateTables(databaseName):\n",
" engine = psqlConnect()\n",
" df.head(0).to_sql(databaseName, engine, if_exists=\"replace\", index=False)\n",
" # disconnect()\n",
" return 0\n",
"\n",
"\n",
"psqlCreateTables(dbname)\n",
"# testar função"
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "a7883c4d-4609-4380-8a45-246b7ca2f9c5",
"metadata": {
"tags": []
},
"outputs": [
{
"ename": "AttributeError",
"evalue": "'int' object has no attribute 'raw_connection'",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
"File \u001b[0;32m:2\u001b[0m\n",
"\u001b[0;31mAttributeError\u001b[0m: 'int' object has no attribute 'raw_connection'"
]
}
],
"source": [
"%%time\n",
"# Write\n",
"conn = engine.raw_connection()\n",
"cur = conn.cursor()\n",
"output = io.StringIO()\n",
"df.to_csv(output, sep=\"\\t\", header=False, index=False)\n",
"output.seek(0)\n",
"contents = output.getvalue()\n",
"\n",
"cur.copy_from(output, \"comparedbs\") # , null=\"\") # null values become ''\n",
"conn.commit()\n",
"cur.close()\n",
"conn.close()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "73de4294-1284-49b0-b31e-45db6e835877",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"id": "e37a93e1-fc0e-4d27-9e16-dca6c8aea324",
"metadata": {},
"outputs": [],
"source": [
"start = time.time()\n",
"# %%time\n",
"# Read\n",
"df = pd.read_sql_query('select * from \"comparedbs\"', con=engine)\n",
"end = time.time()\n",
"postgresql_read_time = exec_time(start, end)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6d1b7480-5bc7-4f08-8cf3-b9590802d8f7",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"print(postgresql_read_time)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6acb2959-3255-43bd-aea5-9ef70acc8902",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"df.head()"
]
},
{
"cell_type": "markdown",
"id": "f9e0393d-7d1d-406a-a068-9dbf4968e977",
"metadata": {
"tags": []
},
"source": [
"### S3 Parquet"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "60a990e2-4607-4654-84ec-17d4985adae2",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"# fazer sem funçao para ver se melhora\n",
"# verifique se esta no ssd os arquivos da pasta git\n",
"def main():\n",
" client = Minio(\n",
" S3MinioUrl,\n",
" secure=False,\n",
" region=S3MinioRegion,\n",
" access_key=\"MatMPA7NyHltz7DQ\",\n",
" secret_key=\"SO1IG5iBPSjNPZanYUaHCLcoSbjphLCP\",\n",
" )\n",
"\n",
" # Make bucket if not exist.\n",
" found = client.bucket_exists(\"data\")\n",
" if not found:\n",
" client.make_bucket(\"data\")\n",
" else:\n",
" print(\"Bucket 'data' already exists\")\n",
"\n",
" # Upload\n",
" client.fput_object(\n",
" \"data\",\n",
" \"data.parquet\",\n",
" \"data/data.parquet\",\n",
" )\n",
" # print(\n",
" # \"'data/data.parquet' is successfully uploaded as \"\n",
" # \"object 'data.parquet' to bucket 'data'.\"\n",
" # )"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "390918c8-c88f-404a-96c4-685d578fdad0",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"%%time\n",
"df.to_parquet(\"data/data.parquet\")\n",
"if __name__ == \"__main__\":\n",
" try:\n",
" main()\n",
" except S3Error as exc:\n",
" print(\"error occurred.\", exc)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a9e07143-8c11-4b68-a869-c3922cda9092",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"pq = pd.read_parquet(\"data/data.parquet\", engine=\"pyarrow\")\n",
"pq.head()"
]
},
{
"cell_type": "markdown",
"id": "50d1fc58-89a7-4507-aff0-6e943656cfe0",
"metadata": {
"tags": []
},
"source": [
"### MongoDB"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d104d9af-fa34-4261-8478-329a28ee4f2e",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"# Load csv dataset\n",
"data = pd.read_csv(\"out.csv\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0af8f72c-5b58-4dfc-af36-c5b4bc79f127",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"# Connect to MongoDB\n",
"client = MongoClient(\n",
" # \"mongodb://192.168.1.133:27017\"\n",
" \"mongodb://{}:{}@{}/EURUSDtest?retryWrites=true&w=majority\".format(\n",
" MongoUser, MongoKey, MongoUrl\n",
" ),\n",
" authSource=\"admin\",\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f1b20d15-f5af-463c-813f-ffae61119de1",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"db = client[\"EUROUSDtest\"]\n",
"collection = db[\"finance\"]\n",
"# data.reset_index(inplace=True)\n",
"data_dict = data.to_dict(\"records\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "70674d23-f375-4659-87ec-c745dec96d54",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"%%time\n",
"# Insert collection\n",
"collection.insert_many(data_dict)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "81a4a33d-5914-45d8-af4e-2b0aabd2ac38",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"# read"
]
},
{
"cell_type": "markdown",
"id": "97405e42-61dc-42c7-8220-237a312c0ec7",
"metadata": {
"tags": []
},
"source": [
"### DuckDB"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bbcdb883-d6dc-46db-88db-4c90b84522ba",
"metadata": {},
"outputs": [],
"source": [
"cursor = duckdb.connect()\n",
"print(cursor.execute(\"SELECT 42\").fetchall())"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "35025a6e-9dc7-46cf-a792-76b3d84f1ac0",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"%%time\n",
"conn = duckdb.connect()\n",
"data = pd.read_csv(\"out.csv\")\n",
"conn.register(\"EURUSDtest\", data)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c6abdaaa-3ac2-425b-9208-d6cb79afe966",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"display(conn.execute(\"SHOW TABLES\").df())"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2acce0f3-f0b2-47d0-8e0d-f9e9687efc18",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"%%time\n",
"df = conn.execute(\"SELECT * FROM EURUSDtest\").df()\n",
"df"
]
},
{
"cell_type": "markdown",
"id": "4409cc89-ed14-4313-ac89-65b826038533",
"metadata": {
"tags": []
},
"source": [
"### Kdb+"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "14f63810-1943-4e28-9bce-2148be6be02d",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"\n",
"np.bool = np.bool_\n",
"from qpython import qconnection"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8ff6c090-7e02-435a-a179-f2aab81da972",
"metadata": {},
"outputs": [],
"source": [
"# read csv\n",
"data = pd.read_csv(\"out.csv\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b4eb8ab9-81e8-4732-8cf7-51f0981d3d57",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"# open connection\n",
"q = qconnection.QConnection(host=\"localhost\", port=5001)\n",
"q.open()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "97cb6b5b-65a5-46a0-a4ee-e5c535a716ab",
"metadata": {},
"outputs": [],
"source": [
"%%time\n",
"# send df to kd+ in memory bank\n",
"q.sendSync(\"{t::x}\", data)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c2ed2d51-bc8e-4207-892a-35fc55d43570",
"metadata": {},
"outputs": [],
"source": [
"# write to on disk table\n",
"q.sendSync(\"`:/home/sandman/q/tab1 set t\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9c055a95-f73f-43a3-8fbd-61e42235117e",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"%%time\n",
"# read from on disk table\n",
"df2 = q.sendSync(\"tab2: get `:/home/sandman/q/tab1\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9760de38-9f04-4322-bfff-c7ee12d5dee5",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"# print(df2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c06c9222-c69d-4872-9d21-052281a013e2",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"%%time\n",
"# load to variable df2\n",
"df2 = q.sendSync(\"tab2\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8815f01c-fd0a-4f94-ab7f-f8ede84ba4e7",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"# df2(type)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e6ed3927-4395-45cd-9a28-88c5db01f2e5",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"%%time\n",
"# converto to dataframe\n",
"df = pd.DataFrame(q(\"t\")) # , pandas=True))\n",
"df.head()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0fc7f16b-6c39-4ebe-88d2-ff857e30ab62",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"%%time\n",
"# select\n",
"df3 = q.sendSync(\"select from t\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c88646ca-3d25-4a85-80b5-f9e559f568dd",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"q.close()"
]
},
{
"cell_type": "markdown",
"id": "7baf1fd1-2afd-41b5-a579-33f053e4ddfc",
"metadata": {},
"source": [
"## Graph\n"
]
},
{
"cell_type": "code",
"execution_count": 66,
"id": "a9740731-6077-4bf1-bb65-b4c4225ac79b",
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"image/png": "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KjefQuXSpUs6ePBgke0HDx5UQUHBVQ8FAAAg+fipnxEjRmjkyJE6duyY95M+u3fv1syZMzVixIhSHRAAAFRePoXKf//3fysyMlKzZs1Senq6JCkqKkoTJkzQE088UaoDAgCAysunUPHz89PEiRM1ceJEZWZmShKLaAEAQKnz+QvfLiNQAABAWfFpMe3333+v+++/X3Xq1FGVKlXk7+9f6AIAAFAafDqjMnz4cJ08eVJPPfWUoqKi5HA4SnsuAAAA30Llk08+0fbt23XDDTeU8jgAAAD/x6e3ftxutyzLKu1ZAAAACvEpVGbPnq3JkyfrxIkTpTwOAADA//HprZ9BgwYpNzdX0dHRqlatmgICAgrd/sMPP5TKcAAAoHLzKVRmz55dymMAAAAU5VOoDBs2rLTnAAAAKMLnL3zLz8/X6tWrdeDAAUlSy5Ytdeedd/I9KgAAoNT4FCpHjx7V7bffru+++05NmzaVJCUlJcntduvDDz9UdHR0qQ4JAAAqJ58+9TNu3DhFR0crLS1NqampSk1N1cmTJ9WwYUONGzeutGcEAACVlE9nVLZu3apdu3apVq1a3m1hYWGaOXOm4uLiSm04AABQufl0RsXpdCorK6vI9uzsbAUGBl71UAAAAJKPodKnTx+NGjVKu3fvlmVZsixLu3bt0kMPPaQ777yztGcEAACVlE+hMmfOHEVHRys2NlZBQUEKCgpSXFycYmJi9PLLL5f2jAAAoJLyaY1KaGio3n//fR09etT78eTmzZsrJiamVIcDAACVm8/foyJJMTExxAkAACgzPr31M3DgQD3//PNFtv/5z3/WPffcc9VDAQAASD6GyrZt23T77bcX2d67d29t27btqocCAACQfAyVX/oYckBAgDIzM0t8nPnz56tNmzYKCQlRSEiIYmNjtXbtWl9GAgAAFZBPodK6dWu99dZbRbavWLFCLVq0KPFx6tWrp5kzZyolJUV79uxR165d1a9fP3311Ve+jAUAACoYnxbTPvXUUxowYICOHTumrl27SpI2btyoN998U++8806Jj9O3b99C12fMmKH58+dr165datmyZZH9PR6PPB6P9/qVnL0BAADXHp/OqPTt21erV6/W0aNHNXr0aD3xxBP65z//qY8//lj9+/f3aZD8/HytWLFCOTk5io2NLXafpKQkuVwu78Xtdvv0WAAA4NrgsCzL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",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"x = np.arange(1)\n",
"width = 0.40\n",
"y1 = [cHouse_read_execution_time]\n",
"y2 = [cHouse_write_execution_time]\n",
"plt.bar(x - 0.2, y1, width)\n",
"plt.bar(x + 0.2, y2, width)\n",
"plt.xticks(x, [\"Click House\"])\n",
"plt.xlabel(\"Databases\")\n",
"plt.ylabel(\"Seconds\")\n",
"plt.legend([\"Read\", \"Write\"]) # ver\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cac1c82a-bcab-47b1-b302-77d1341e5304",
"metadata": {},
"outputs": [],
"source": []
}
],
"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.10.11"
},
"widgets": {
"application/vnd.jupyter.widget-state+json": {
"state": {},
"version_major": 2,
"version_minor": 0
}
}
},
"nbformat": 4,
"nbformat_minor": 5
}