rust 如何加快解析40Gb txt文件并将每行插入一行到sqlite数据库的过程

14ifxucb  于 2023-08-05  发布在  SQLite
关注(0)|答案(1)|浏览(107)

背景

我目前正在尝试解析一个.txt com区域文件。它的结构是这样的

blahblah.com    xx     xx      examplens.com

字符串
目前我的代码结构是这样的

extern crate regex;
use regex::Regex;
use rusqlite::{params, Connection, Result};

#[derive(Debug)]
struct Domain {
    id: i32,
    domain: String,
}

use std::io::stdin;
fn main() -> std::io::Result<()> {
    
    let mut reader = my_reader::BufReader::open("data/com_practice.txt")?;
    let mut buffer = String::new();
    let conn: Connection = Connection::open("/Users/alex/Projects/domain_randomizer/data/domains.db").unwrap();
    
    while let Some(line) = reader.read_line(&mut buffer) {
        let regexed_i_think = rexeginton_the_domain_only(line?.trim());
        println!("{:?}", regexed_i_think);
        sqliting(regexed_i_think, &conn).unwrap();
    }
    
    let mut stmt = conn.prepare("SELECT id, domain FROM domains").unwrap();

    let domain_iter = stmt.query_map(params![], |row| {
        Ok(Domain {
            id: row.get(0)?,
            domain: row.get(1)?,
        })
    }).unwrap();

    for domain in domain_iter {
        println!("Found person {:?}", domain.unwrap());
    }

    Ok(())
}

pub fn sqliting(domain_name: &str, conn: &Connection) -> Result<()> {

    let yeah = Domain {
        id: 0,
        domain: domain_name.to_string()
    };

    conn.execute(
        "INSERT INTO domains (domain) VALUES (?1)",
        params![yeah.domain],
    )?;

    Ok(())
}

mod my_reader {
    use std::{
        fs::File,
        io::{self, prelude::*},
    };

    pub struct BufReader {
        reader: io::BufReader<File>,
    }

    impl BufReader {
        pub fn open(path: impl AsRef<std::path::Path>) -> io::Result<Self> {
            let file = File::open(path)?;
            let reader = io::BufReader::new(file);

            Ok(Self { reader })
        }

        pub fn read_line<'buf>(
            &mut self,
            buffer: &'buf mut String,
        ) -> Option<io::Result<&'buf mut String>> {
            buffer.clear();

            self.reader
                .read_line(buffer)
                .map(|u| if u == 0 { None } else { Some(buffer) })
                .transpose()
        }
    }
}

pub fn rexeginton_the_domain_only(full_line: &str) -> &str {
    let regex_str = Regex::new(r"(?m).*?.com").unwrap();
    let final_str = regex_str.captures(full_line).unwrap().get(0).unwrap().as_str();
    return final_str;
}

问题

所以我一次解析一个域,每次都做一个插入。正如我所收集的,如果我在一个事务中进行数千次插入,插入将更加有效。但是,我不太确定围绕这个问题重构解析的有效方法是什么。

问题

我应该如何围绕插入过程重新定位解析过程?还有,我如何能够主动地衡量过程的速度和效率,以便我能够以清晰的方式进行比较和对比?

fhg3lkii

fhg3lkii1#

1.使用journal_mode=WAL打开数据库,如果不需要持久性,则使用synchronous=off
1.创建交易
1.创建预准备语句
1.重复execute准备好的语句
作为一种健全性检查,您还可以分析您的程序,看看sqlite是瓶颈的假设是否正确。

相关问题