Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在sqlite3/Python中的“选择”过程中缓存了哪些数据,可以从一开始就手动完成吗?_Python_Caching_Sqlite_Query Optimization - Fatal编程技术网

在sqlite3/Python中的“选择”过程中缓存了哪些数据,可以从一开始就手动完成吗?

在sqlite3/Python中的“选择”过程中缓存了哪些数据,可以从一开始就手动完成吗?,python,caching,sqlite,query-optimization,Python,Caching,Sqlite,Query Optimization,假设您有一个包含数千行的sqlite数据库,其中每一行都包含或引用一个较大的、唯一的blob,并且您希望稀疏地对该集合进行采样,根据rowid或一些等效的主键提取行。我发现,在连接20k行之后,我第一次尝试获取500个数据点时,调用需要10秒钟才能返回;而且,随着每次连续迭代,调用会越来越短,直到在50-100次这样的查询后收敛到大约100毫秒 显然,sqlite或其python包装器都必须缓存。。。某物如果我清除非活动内存,我在OSX中,但是我认为Linux有一个类似的清除命令,如果不是完全相

假设您有一个包含数千行的sqlite数据库,其中每一行都包含或引用一个较大的、唯一的blob,并且您希望稀疏地对该集合进行采样,根据rowid或一些等效的主键提取行。我发现,在连接20k行之后,我第一次尝试获取500个数据点时,调用需要10秒钟才能返回;而且,随着每次连续迭代,调用会越来越短,直到在50-100次这样的查询后收敛到大约100毫秒

显然,sqlite或其python包装器都必须缓存。。。某物如果我清除非活动内存,我在OSX中,但是我认为Linux有一个类似的清除命令,如果不是完全相同的话,那么这个行为可以完全复制。问题是,索引没有处理的缓存是什么?此外,是否有可能从一开始就自动将加速这些查询的任何信息拉入内存?还是我完全错过了什么

如果有人不马上知道答案,请记下一些注意事项

每个blob大约为40kB,是问题的一个很大的ha来源。下面我为那些想在家里玩的人提供了一些代码,但我更幸运的是为可排序的信息和数据保留了单独的表。这引入了一个内部连接,但总的来说,它比把所有的连接在一起要好,尽管如果有人觉得这是错误的,我很想听听。如果没有内部连接/数据获取,事情从4秒开始,然后迅速下降到3毫秒

我觉得这可能是一个布拉格的东西,但我摆弄了一些设置建议的其他人在荒野的网络,并没有真正看到任何好处

内存中的数据库不是一个选项。首先,我正在尝试跨线程共享,这对mems来说可能不是问题。。。?不确定,但更重要的是,数据库文件通常为17 GB左右。那么,就这样了

也就是说,缓存合理数量的信息没有问题。经过几十次调用后,非活动内存无论如何都会有些膨胀,但我宁愿正确地执行1,高效地执行2

好的,现在给那些想要复制东西的人一些代码。您应该能够将它复制并粘贴到一个独立的脚本中,这基本上就是我所做的,保存格式

import sqlite3
import numpy as np
import time

ref_uid_index = """CREATE INDEX ref_uid_idx
                   ON data(ref_uid)"""


def populate_db_split(db_file, num_classes=10, num_points=20000, VERBOSE=False):
    def_schema_split0 = """
    CREATE TABLE main (
        uid            INTEGER PRIMARY KEY,
        name           TEXT,
        label          INTEGER,
        ignore         INTEGER default 0,
        fold           INTEGER default 0)"""

    def_schema_split1 = """
        CREATE TABLE data (
            uid            INTEGER PRIMARY KEY,
            ref_uid        INTEGER REFERENCES main(uid),
            data           BLOB)"""

    def_insert_split0 = """
        INSERT INTO main (name, label, fold)
            VALUES (?,?,?)"""

    def_insert_split1 = """
        INSERT INTO data (ref_uid, data)
            VALUES (?,?)"""

    blob_size= 5000
    k_folds = 5
    some_names = ['apple', 'banana', 'cherry', 'date']

    dbconn = sqlite3.connect(db_file)
    dbconn.execute(def_schema_split0)
    dbconn.execute(def_schema_split1)

    rng = np.random.RandomState()
    for n in range(num_points):
        if n%1000 == 0 and VERBOSE:
            print n

        # Make up some data
        data = buffer(rng.rand(blob_size).astype(float))
        fold = rng.randint(k_folds)
        label = rng.randint(num_classes)
        rng.shuffle(some_names)

        # And add it
        dbconn.execute(def_insert_split0,[some_names[0], label, fold])
        ref_uid = dbconn.execute("SELECT uid FROM main WHERE rowid=last_insert_rowid()").fetchone()[0]
        dbconn.execute(def_insert_split1,[ref_uid,data])

    dbconn.execute(ref_uid_index)
    dbconn.commit()
    return dbconn

def timeit_join(dbconn, n_times=10, num_rows=500):
    qmarks = "?,"*(num_rows-1)+"?"

    q_join = """SELECT data.data, main.uid, main.label
              FROM data INNER JOIN main ON main.uid=data.ref_uid
              WHERE main.uid IN (%s)"""%qmarks

    row_max = dbconn.execute("SELECT MAX(rowid) from main").fetchone()[0]

    tstamps = []
    for n in range(n_times):
        now = time.time()
        uids = np.random.randint(low=1,high=row_max,size=num_rows).tolist()
        res = dbconn.execute(q_join, uids).fetchall()

        tstamps += [time.time()-now]
        print tstamps[-1]
现在,如果您想复制东西,请执行以下操作。在我的机器上,这会创建一个800MB的数据库,并生成如下内容

>>> db = populate_db_split('/some/file/path.db')
>>> timeit_join(db)
12.0593519211
5.56209111214
3.51154184341
2.20699000359
1.73895692825
1.18351387978
1.27329611778
0.934082984924
0.780968904495
0.834318161011

所以。。。你说呢,博学的圣人?

GB大小的数据库文件永远不会完全加载到内存中。它们被分成一棵所谓的书页树。这些页面缓存在内存中,默认为2000页

您可以使用以下语句将1kB大小的缓存页面数增加一倍

    conn.execute("""PRAGMA cache_size = 4000""")
正如您在函数描述中所看到的,该连接同样具有最后100条语句的缓存:

    sqlite3.connect(database[, timeout, detect_types, isolation_level, check_same_thread, factory, cached_statements])
缓存的_语句需要和整数,默认为100


除了设置缓存大小之外,在应用程序启动时主动缓存语句或页面可能不会给您带来好处

人力资源管理。。。有没有办法增加页面大小?如果我的表中有每个40k的blob,那么它不是在扫描40页基本上什么都没有的内容来获取每1个有用的可排序信息吗?我会尝试一下,看看会有什么结果