This commit is contained in:
2025-10-28 01:38:59 +08:00
parent d570cc98a1
commit c5f14c2a97
10 changed files with 264 additions and 39 deletions

0
.env.example Normal file
View File

3
.gitignore vendored
View File

@@ -1,3 +1,6 @@
.env
node_modules
dist
./docker/data
!.env*.example

View File

@@ -0,0 +1,25 @@
<?xml version="1.0"?>
<yandex>
<logger>
<level>information</level>
<console>true</console>
</logger>
<http_port>8123</http_port>
<tcp_port>9000</tcp_port>
<listen_host>::</listen_host>
<max_connections>4096</max_connections>
<keep_alive_timeout>3</keep_alive_timeout>
<max_concurrent_queries>100</max_concurrent_queries>
<path>/var/lib/clickhouse/</path>
<tmp_path>/var/lib/clickhouse/tmp/</tmp_path>
<user_files_path>/var/lib/clickhouse/user_files/</user_files_path>
<users_config>users.xml</users_config>
<default_profile>default</default_profile>
<default_database>default</default_database>
</yandex>

View File

@@ -0,0 +1,34 @@
<?xml version="1.0"?>
<yandex>
<profiles>
<default>
<max_memory_usage>10000000000</max_memory_usage>
<use_uncompressed_cache>0</use_uncompressed_cache>
<load_balancing>random</load_balancing>
</default>
</profiles>
<users>
<default>
<password>password</password>
<networks>
<ip>::/0</ip>
</networks>
<profile>default</profile>
<quota>default</quota>
</default>
</users>
<quotas>
<default>
<interval>
<duration>3600</duration>
<queries>0</queries>
<errors>0</errors>
<result_rows>0</result_rows>
<read_rows>0</read_rows>
<execution_time>0</execution_time>
</interval>
</default>
</quotas>
</yandex>

26
docker/compose.yml Normal file
View File

@@ -0,0 +1,26 @@
services:
clickhouse:
image: clickhouse/clickhouse-server:latest
container_name: clickhouse-server
ports:
- "8123:8123" # HTTP接口
- "9000:9000" # TCP接口
volumes:
- ./data/clickhouse_data:/var/lib/clickhouse
- ./data/clickhouse_logs:/var/log/clickhouse-server
- ./clickhouse/config.xml:/etc/clickhouse-server/config.xml
- ./clickhouse/users.xml:/etc/clickhouse-server/users.xml
environment:
- CLICKHOUSE_DB=default
- CLICKHOUSE_USER=default
- CLICKHOUSE_PASSWORD=password
ulimits:
nofile:
soft: 262144
hard: 262144
networks:
- clickhouse-network
networks:
clickhouse-network:
driver: bridge

View File

@@ -10,14 +10,14 @@
"keywords": [],
"author": "abearxiong <xiongxiao@xiongxiao.me> (https://www.xiongxiao.me)",
"license": "MIT",
"packageManager": "pnpm@10.6.2",
"packageManager": "pnpm@10.19.0",
"type": "module",
"dependencies": {
"@clickhouse/client": "^1.11.0",
"dotenv": "^16.4.7"
"@clickhouse/client": "^1.12.1",
"dotenv": "^17.2.3"
},
"devDependencies": {
"@types/node": "^22.13.11",
"typescript": "^5.8.2"
"@types/node": "^24.9.1",
"typescript": "^5.9.3"
}
}

56
pnpm-lock.yaml generated
View File

@@ -9,57 +9,57 @@ importers:
.:
dependencies:
'@clickhouse/client':
specifier: ^1.11.0
version: 1.11.0
specifier: ^1.12.1
version: 1.12.1
dotenv:
specifier: ^16.4.7
version: 16.4.7
specifier: ^17.2.3
version: 17.2.3
devDependencies:
'@types/node':
specifier: ^22.13.11
version: 22.13.11
specifier: ^24.9.1
version: 24.9.1
typescript:
specifier: ^5.8.2
version: 5.8.2
specifier: ^5.9.3
version: 5.9.3
packages:
'@clickhouse/client-common@1.11.0':
resolution: {integrity: sha512-O0xbwv7HiMXayokrf5dYIBpjBnYekcOXWz60T1cXLmiZ8vgrfNRCiOpybJkrMXKnw9D0mWCgPUu/rgMY7U1f4g==}
'@clickhouse/client-common@1.12.1':
resolution: {integrity: sha512-ccw1N6hB4+MyaAHIaWBwGZ6O2GgMlO99FlMj0B0UEGfjxM9v5dYVYql6FpP19rMwrVAroYs/IgX2vyZEBvzQLg==}
'@clickhouse/client@1.11.0':
resolution: {integrity: sha512-VYTQfR0y/BtrIDEjuSce1zv85OvHak5sUhZVyNYJzbAgWHy3jFf8Os7FdUSeqyKav0xGGy+2X+dRanTFjI5Oug==}
'@clickhouse/client@1.12.1':
resolution: {integrity: sha512-7ORY85rphRazqHzImNXMrh4vsaPrpetFoTWpZYueCO2bbO6PXYDXp/GQ4DgxnGIqbWB/Di1Ai+Xuwq2o7DJ36A==}
engines: {node: '>=16'}
'@types/node@22.13.11':
resolution: {integrity: sha512-iEUCUJoU0i3VnrCmgoWCXttklWcvoCIx4jzcP22fioIVSdTmjgoEvmAO/QPw6TcS9k5FrNgn4w7q5lGOd1CT5g==}
'@types/node@24.9.1':
resolution: {integrity: sha512-QoiaXANRkSXK6p0Duvt56W208du4P9Uye9hWLWgGMDTEoKPhuenzNcC4vGUmrNkiOKTlIrBoyNQYNpSwfEZXSg==}
dotenv@16.4.7:
resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==}
dotenv@17.2.3:
resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==}
engines: {node: '>=12'}
typescript@5.8.2:
resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==}
typescript@5.9.3:
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
engines: {node: '>=14.17'}
hasBin: true
undici-types@6.20.0:
resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==}
undici-types@7.16.0:
resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
snapshots:
'@clickhouse/client-common@1.11.0': {}
'@clickhouse/client-common@1.12.1': {}
'@clickhouse/client@1.11.0':
'@clickhouse/client@1.12.1':
dependencies:
'@clickhouse/client-common': 1.11.0
'@clickhouse/client-common': 1.12.1
'@types/node@22.13.11':
'@types/node@24.9.1':
dependencies:
undici-types: 6.20.0
undici-types: 7.16.0
dotenv@16.4.7: {}
dotenv@17.2.3: {}
typescript@5.8.2: {}
typescript@5.9.3: {}
undici-types@6.20.0: {}
undici-types@7.16.0: {}

View File

@@ -3,16 +3,135 @@ import { createClient } from '@clickhouse/client';
dotenv.config();
// 定义数据类型接口
interface DataRecord {
id: number;
title: string;
description: string;
created_at: Date;
}
const clickhouse = createClient({
url: process.env.CLICKHOUSE_URL,
username: process.env.CLICKHOUSE_USERNAME,
password: process.env.CLICKHOUSE_PASSWORD,
});
clickhouse
.query({
query: 'SELECT 1',
})
.then((res) => {
console.log(res);
// 生成随机数据的函数
function generateRandomData(count: number): DataRecord[] {
const titles = [
'人工智能的未来', '云计算发展趋势', '区块链技术应用', '大数据分析实践',
'机器学习入门', '网络安全防护', '物联网架构设计', '5G技术展望',
'量子计算突破', '自动驾驶技术', '虚拟现实体验', '智能家居系统',
'数字化转型', '边缘计算应用', '分布式存储方案', '微服务架构实践',
'容器化部署', 'DevOps最佳实践', 'API设计原则', '数据库优化技巧'
];
const descriptions = [
'深入探讨技术发展趋势和未来前景,为行业发展提供重要参考。',
'详细介绍技术原理和实现方法,帮助读者快速掌握核心概念。',
'分析实际应用场景和案例研究,展示技术的实际价值。',
'总结最佳实践和经验教训,避免常见陷阱和错误。',
'展望未来发展方向和机遇挑战,为决策提供依据。'
];
const data: DataRecord[] = [];
const now = new Date();
for (let i = 1; i <= count; i++) {
data.push({
id: i,
title: titles[Math.floor(Math.random() * titles.length)],
description: descriptions[Math.floor(Math.random() * descriptions.length)],
created_at: new Date(now.getTime() - Math.floor(Math.random() * 30 * 24 * 60 * 60 * 1000))
});
}
return data;
}
// 创建表
async function createTable() {
const createTableQuery = `
CREATE TABLE IF NOT EXISTS data_records (
id UInt32,
title String,
description String,
created_at DateTime
) ENGINE = MergeTree()
ORDER BY id
`;
await clickhouse.query({
query: createTableQuery,
});
console.log('Table created or already exists');
}
// 插入数据 - 修复数据格式问题
async function insertData(records: DataRecord[]) {
// 将数据转换为JSONEachRow格式需要的对象数组
const values = records.map(record => ({
id: record.id,
title: record.title,
description: record.description,
created_at: record.created_at.toISOString().slice(0, 19).replace('T', ' ')
}));
await clickhouse.insert({
table: 'data_records',
values: values,
format: 'JSONEachRow'
});
console.log(`Inserted ${records.length} records`);
}
// 主函数
async function main() {
try {
// 测试连接
const pingResult = await clickhouse.query({
query: 'SELECT 1 as ping',
});
console.log('Connected to ClickHouse');
// 创建表
await createTable();
// 生成20条随机数据
const randomData = generateRandomData(20);
console.log('Generated 20 random records');
// 插入数据
await insertData(randomData);
// 验证数据
const result = await clickhouse.query({
query: 'SELECT COUNT(*) as total FROM data_records',
});
const countData = await result.json() as { data: { total: string }[] };
console.log('Total records in table:', countData.data[0].total);
// 显示前5条记录
const sample = await clickhouse.query({
query: 'SELECT id, title, description FROM data_records ORDER by id LIMIT 5',
});
const sampleData = await sample.json() as { data: Array<{ id: number; title: string; description: string }> };
console.log('Sample records:');
sampleData.data.forEach((record) => {
console.log(`${record.id}: ${record.title} - ${record.description}`);
});
} catch (error) {
console.error('Error:', error);
} finally {
await clickhouse.close();
}
}
// 运行主函数
main();

0
src/demo.ts Normal file
View File

18
src/demo/connect.ts Normal file
View File

@@ -0,0 +1,18 @@
import dotenv from 'dotenv';
import { createClient } from '@clickhouse/client';
dotenv.config();
const clickhouse = createClient({
url: process.env.CLICKHOUSE_URL,
username: process.env.CLICKHOUSE_USERNAME,
password: process.env.CLICKHOUSE_PASSWORD,
});
clickhouse
.query({
query: 'SELECT 1',
})
.then((res) => {
console.log('SELECT 1');
});