У меня есть сценарий, который требует, чтобы все файлы в заданном каталоге были проиндексированы для упрощения запросов (например, найти файл с заданным именем файла, имеющим самую последнюю дату изменения). Я просматривал весь каталог и добавлял каждый файл в фрейм данных каждый раз, когда запускался скрипт. Я бы подумал, что вместо того, чтобы собирать эти данные для каждого файла, было бы быстрее запросить базу данных и обновлять только в том случае, если измененные данные файлов изменились, но при тестировании это было намного медленнее. Почему это? Есть ли более эффективный способ сделать это?
Результат:
Index with pandas took 0:06:53.352515
Innitial index with SQLite3 took 0:43:20.042651
second index with SQLite3 took 0:21:48.863566
"""
{Description}
The purpose of this exercise is to index a directory for later use.
We will try two methods to quantify the benefits of updating a SQLite db
rather than re-indexing into a pandas dataframe each time.
"""
# Built-in/Generic Imports
import os
import sys
# […]
# Libs
import pandas as pd # Or any other
import datetime
import sqlite3
def main():
dbPath = os.path.join(os.getcwd(), 'testing.db')
indexPath = Random_Directory_with_tons_of_files
setupSQL(dbPath)
print('Index with pandas took ' + str(testPandas(indexPath)))
print('Innitial index with SQLite3 took ' + str(testSQLite(indexPath, dbPath)))
print('second index with SQLite3 took ' + str(testSQLite(indexPath, dbPath)))
def setupSQL(dbPath):
if os.path.exists(dbPath):
os.remove(dbPath)
conn = sqlite3.connect(dbPath)
c = conn.cursor()
c.execute('''CREATE TABLE testTable
(fullPath, fileName, modifiedDate)''')
conn.commit()
conn.close()
def testPandas(path):
startTime = datetime.datetime.now()
testIndex = pd.DataFrame(columns=['fullPath', 'fileName', 'modifiedDate'])
for dirpath, dirnames, filenames in os.walk(path):
for filename in filenames:
testIndex = testIndex.append({'fullPath' : os.path.join(dirpath, filename),
'fileName' : filename,
'modifiedDate' : os.path.getmtime(os.path.join(dirpath, filename))}, ignore_index=True)
return datetime.datetime.now() - startTime
def testSQLite(path, dbPath):
startTime = datetime.datetime.now()
conn = sqlite3.connect(dbPath)
c = conn.cursor()
for dirpath, dirnames, filenames in os.walk(path):
for filename in filenames:
c.execute('SELECT * FROM testTable WHERE fullPath=?', [(os.path.join(dirpath, filename))])
row = c.fetchone()
if row == None:
#File is not in database, add it
c.execute('INSERT INTO testTable VALUES (?,?,?)', [
(os.path.join(dirpath, filename)),
(filename),
(os.path.getmtime(os.path.join(dirpath, filename)))
])
conn.commit()
elif row[2] != os.path.getmtime(os.path.join(dirpath, filename)):
#Modified Date has changed, update it.
c.execute('UPDATE testTable SET modifiedDate=? WHERE fullPath=?', [(os.path.getmtime(os.path.join(dirpath, filename))),(os.path.join(dirpath, filename))])
conn.commit()
conn.close()
return datetime.datetime.now() - startTime
if __name__ == '__main__':
print('Starting')
main()
print('Done')