如何使用 sqlite3 正确实现用于变量 LIKE 语句的索引?

How to properly implement indexing for use in variable LIKE statement with sqlite3?

我正在尝试在两个 table 之间进行一些模糊匹配。 一个是我在本地存储的 table(9,000 行),称之为 table A。另一个存储为 sqlite db(200 万 + 行 csv),称之为 table B . 基本上,我想将 table A 中的 "CompanyNames" 列与 table B 中的 "CurrentEntityNames" 列相匹配,并使用它左连接 table B 到 table A.

我目前能够循环遍历 LIKE 语句,传递如下参数: (myNames 只是来自 table A 的列 CompanyNames 作为列表)。

for index, name in enumerate(myNames):
        sql = 'SELECT * from "table" WHERE CurrentEntityName LIKE ?;'
        param =(name + '%%',)
        df = pd.read_sql_query(sql,engine, params=param)
        myresponses[index] = df

但是,我有两个问题: 1. 我意识到查询 table A 中的每一行可能不是很有效,因为目标是尽量减少与数据库的交互。 如果最好重组以减少查询,我该怎么做? 2. 添加基于 CurrentEntityName 的索引是否会加快速度?

对于方法 2.,我尝试使用(在另一个 Whosebug 答案中找到)

添加索引
meta = sqlalchemy.MetaData()
meta.reflect(bind=engine)
table = meta.tables['table']
my_index = sqlalchemy.Index('nameIds', table.columns.get('CurrentEntityName'))

但我不确定在查询时如何实现。

对于方法 1,我看过一些使用 conn 和 cursor 的示例,但实际上我不确定如何将它们与从引擎创建的数据库结合使用。 (我使用

加载了我的数据
for df in pd.read_csv("C://Users//SEAB//Downloads//Active_Corporations___Beginning_1800.csv", chunksize = chunksize, iterator = True):
    df = df.rename(columns={c:c.replace(' ', '')  for c in df.columns})
    df.index +=j
    i+=1
    df.to_sql('table', engine, if_exists = 'append')
    j= df.index[-1] + 1

在本教程中找到 [https://plot.ly/python/v3/big-data-analytics-with-pandas-and-sqlite/]

基本上,查询仍然很慢(9000 行可能需要 1 个多小时)。 我真的很感谢任何建议或帮助。我是 sqlite3 的新手,所以有很多我不知道。感谢您的理解。

The rules 因为当 Sqlite 可以使用索引时 LIKE 很多,但它可以做到。

本质上,考虑到默认的不区分大小写的行为:您需要一个在左侧带有 TEXT affinity 的列。右侧需要是格式为 'XXX%' 的字符串文字(或者,如果语句是使用 sqlite3_prepare_v2() 编译的,则参数绑定到字符串) - 即任何前导常量值通配符。鉴于此,如果左侧列有不区分大小写的索引,它可以重写查询以使用该索引而不是查看每一行。

交互式会话中的一些示例:

sqlite> CREATE TABLE ex(col1 TEXT, col2 TEXT COLLATE NOCASE);
sqlite> CREATE INDEX ex_col1_idx ON ex(col1);
sqlite> CREATE INDEX ex_col2_idx ON ex(col2);
sqlite> EXPLAIN QUERY PLAN SELECT * FROM ex WHERE col1 LIKE 'foo%';
QUERY PLAN
`--SCAN TABLE ex
sqlite> EXPLAIN QUERY PLAN SELECT * FROM ex WHERE col2 LIKE 'foo%';
QUERY PLAN
`--SEARCH TABLE ex USING INDEX ex_col2_idx (col2>? AND col2<?)
sqlite> CREATE INDEX ex_col1_idx_nocase ON ex(col1 COLLATE NOCASE);
sqlite> EXPLAIN QUERY PLAN SELECT * FROM ex WHERE col1 LIKE 'foo%';
QUERY PLAN
`--SEARCH TABLE ex USING INDEX ex_col1_idx_nocase (col1>? AND col1<?)
sqlite> .parameter init
sqlite> .parameter set ?1 'foo%'
sqlite> EXPLAIN QUERY PLAN SELECT * FROM ex WHERE col1 LIKE ?;
QUERY PLAN
`--SEARCH TABLE ex USING INDEX ex_col1_idx_nocase (col1>? AND col1<?)

如您所见,要搜索的索引列需要在 table 定义中明确指定不区分大小写的排序规则,或者具有明确不区分大小写的索引。

在你的情况下,事情变坏的巨大潜力是 Python sqlite 绑定如何准备与 execute 方法一起使用的语句 - 它使用旧的 sqlite3_prepare() 还是更新的sqlite3_prepare_v2()API?如果我正在看 the right source file 它使用后者,所以这应该不是问题。