파일 시스템 대 SQLite 성능

12133 단어 performancesqlite
나는 SQL을 싫어한다. 그것은 알려진 사실입니다. 얼마 전에 werc "정상적인 웹 안티 프레임워크"에 대해 읽고 주석 플러그인이 데이터베이스 대신 파일과 디렉토리에 주석을 저장하는 방법을 읽었습니다. 미쳤지? 나는 그것이 미쳤다라고 생각했다. 그러나 동시에 나는 그것이 내가 상상할 수 있는 가장 낭만적인 일이라고 생각했습니다. SQL 데이터베이스가 필요하지 않으면 지상낙원이 될 것입니다!

가장 큰 단점은 성능이라고 생각했습니다. 확실히 파일 시스템은 SQL 데이터베이스에 비해 너무 느릴 것입니다. 그것은 응용 프로그램을 비현실적으로 만들 것입니다. 하지만 테스트 없이는 그런 판단을 하지 않는 법을 배웠습니다. 그래서 내가 했다.

정수 기본 키와 문자열 토큰인 두 개의 필드를 사용하여 100,000개의 임의 레코드를 생성하는 테스트를 작성했습니다. 그것들을 모두 SQLite 데이터베이스와 디렉토리 계층에 삽입한 다음 그 중 일부에 있을 것이라고 알고 있는 작은 문자열을 모두 검색합니다. DB와 파일 시스템에 동일한 레코드를 사용하도록 했습니다.

import sqlite3
import secrets, os, datetime

db = sqlite3.connect("test.db")

def create():
    with db:
        db.execute("CREATE TABLE things (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, val TEXT)")

def populate():
    print("BULK INSERT")
    data = [
        (secrets.token_urlsafe(), secrets.token_urlsafe())
        for i in range(3)
    ]
    before = datetime.datetime.now()
    with db:
        db.executemany("INSERT INTO things (name, val) VALUES (?, ?)", data)
    print(f"db took {datetime.datetime.now() - before}")
    before = datetime.datetime.now()
    for i, thing in enumerate(data):
        os.mkdir('fs/'+str(i))
        with open(f'fs/{i}/name', 'w') as f:
            f.write(thing[0])
        with open(f'fs/{i}/val', 'w') as f:
            f.write(thing[1])
    print(f"fs took {datetime.datetime.now() - before}")

def query():
    query = 'abc'
    print(f"QUERY FOR {query}")
    before = datetime.datetime.now()
    with db:
        for result in db.execute("SELECT id FROM things WHERE name LIKE ? OR val LIKE ?", (f'%{query}%', f'%{query}%')):
            print(f"found result: {result}")
    print(f"db took {datetime.datetime.now() - before}")
    before = datetime.datetime.now()
    for thing in os.listdir('fs'):
        with open(f"fs/{thing}/name") as namef, open(f"fs/{thing}/val") as valf:
            if query in namef.read() or query in valf.read():
                print(f"found result: {thing}")
    print(f"fs took {datetime.datetime.now() - before}")

create()
populate()
query()



BULK INSERT
db took 0:00:00.177113
fs took 0:00:08.010363
QUERY FOR abc
...
db took 0:00:00.023509
...
fs took 0:00:02.868744


슬프게도 내 말이 맞았다. 파일 시스템은 SQL 데이터베이스보다 엄청나게 느립니다.

SQLite 라이브러리는 C 확장이기 때문에 Python의 느림이 FS에서는 큰 차이를 만들지만 DB에서는 그렇지 않다고 생각했습니다. 만일을 대비하여 FS 쿼리에 Crystal을 사용해 보았지만 거의 같았습니다.

Dir.new("fs").children.each do |thing|
  if File.read("fs/#{thing}/name").includes?("abc") || File.read("fs/#{thing}/val").includes?("abc")
    puts thing
  end
end


검색을 많이 해야 하는 웹사이트에 werc가 합리적이지 않은지, 아니면 Plan 9의 파일 시스템이 합리적으로 만드는지 궁금합니다.

좋은 웹페이지 즐겨찾기