【问题标题】:How can I avoid string conversions when ingesting timestamps to postgres in Rust?在 Rust 中向 postgres 插入时间戳时如何避免字符串转换?
【发布时间】:2021-01-21 11:04:48
【问题描述】:

我正在使用rust-postgres crate 来提取数据。这是一个成功添加行的工作示例:

    let name: &str = "hello from rust";
    let val: i32 = 123;
    let now: DateTime<Utc> = Utc::now();
    let timestamp = now.format("%Y-%m-%dT%H:%M:%S%.6f").to_string();
    client.execute(
        "INSERT INTO trades VALUES(to_timestamp($1, 'yyyy-MM-ddTHH:mm:ss.SSSUUU'),$2,$3)",
        &[&timestamp, &name, &val],
    )?;

这看起来不太好,因为我必须进行前后字符串转换,我希望能够编写类似的东西

    let name: &str = "hello from rust";
    let val: i32 = 123;
    let now: DateTime<Utc> = Utc::now();
    client.execute(
        "INSERT INTO trades VALUES($1,$2,$3)",
        &[&now, &name, &val],
    )?;

以这种方式获取时间戳的最高效方式是什么?

编辑:

这是上面第二个示例返回的错误

Error: Error { kind: ToSql(0), cause: Some(WrongType { postgres: Timestamp, rust: "chrono::datetime::DateTime<chrono::offset::utc::Utc>" }) }

我的cargo.toml 看起来像这样(它为 rust postgres crate 启用了计时功能):

[dependencies]
chrono = "0.4.19"
postgres={version="0.19.0", features=["with-serde_json-1", "with-bit-vec-0_6", "with-chrono-0_4"]}

【问题讨论】:

  • 这取决于您的数据库架构,但也许您可以只存储它的 unix 时间戳(u64?)。
  • 虽然这不会是一个巨大的优化,但 DBMS 本身会导致比 2 个额外的字符串转换更大的延迟

标签: postgresql rust questdb


【解决方案1】:

我认为问题在于您的 postgres 架构和 Rust 类型不匹配:错误似乎表明您的 postgres 类型是 timestamp,而您的 rust 类型是 DateTime&lt;Utc&gt;

如果您检查the conversion tableDateTime&lt;Utc&gt; 将转换为TIMESTAMP WITH TIME ZONE。转换为TIMESTAMP 的唯一类型是NaiveDateTimePrimitiveDateTime

【讨论】:

  • 所以在utc = Utc::now(); 和我插入&amp;[&amp;utc.naive_local(), &amp;_name, &amp;_val] 的地方应该可以使用这些方法?
  • 我使用 chrono 的次数不多,但我猜想,或者更改架构以存储时间戳记。
【解决方案2】:

根据Masklinn's response,我需要传递NaiveDateTime 类型才能使其工作,naive_local 的完整示例如下所示:

use postgres::{Client, NoTls, Error};
use chrono::{Utc};
use std::time::SystemTime;

fn main() -> Result<(), Error> {
    let mut client = Client::connect("postgresql://admin:quest@localhost:8812/qdb", NoTls)?;

    // Basic query
    client.batch_execute("CREATE TABLE IF NOT EXISTS trades (ts TIMESTAMP, date DATE, name STRING, value INT) timestamp(ts);")?;

    // Parameterized query
    let name: &str = "rust example";
    let val: i32 = 123;
    let utc = Utc::now();
    let sys_time = SystemTime::now();
    client.execute(
        "INSERT INTO trades VALUES($1,$2,$3,$4)",
        &[&utc.naive_local(), &sys_time, &name, &val],
    )?;

    // Prepared statement
    let mut txn = client.transaction()?;
    let statement = txn.prepare("insert into trades values ($1,$2,$3,$4)")?;
    for value in 0..10 {
        let utc = Utc::now();
        let sys_time = SystemTime::now();
        txn.execute(&statement, &[&utc.naive_local(), &sys_time, &name, &value])?;
    }
    txn.commit()?;

    println!("import finished");
    Ok(())
}

【讨论】:

    猜你喜欢
    • 2021-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-14
    • 1970-01-01
    • 2020-11-22
    • 2018-10-08
    • 2012-10-03
    相关资源
    最近更新 更多