코드
from time import time
import sqlite3
from decimal import Decimal
path = '{white.seolpyo.com}.db'
table = '{하얀설표 블로그}'
sq = sqlite3.connect(':memory:')
with sqlite3.connect(path) as db:
db.backup(sq)
c = sq.cursor()
d = {}
t = time()
for i in c.execute(f'select * from {table}').fetchall():
d[종목코드] = {
'종목코드': 종목코드,
'종목명': 종목명,
'시가': 시가,
'고가': 고가,
'저가': 저가,
'종가': 종가,
'거래량': Decimal(거래량),
}
print(time() - t)
# for k, v in d.items():
# print(k, v)
print(f'{len(d)=}')
print(f"{d['005930']=}")
deci = Decimal('1000')
def aa():
t = time()
[k for k, v in d.items() if v['거래량'] > deci]
print(time() - t)
def bb():
t = time()
c.execute(f'select 종목코드 from {table} where cast(거래량 as decimal) > 1000').fetchall()
print(time() - t)
def cc():
t = time()
sorted([k for k, v in d.items() if v['거래량'] > deci], key=lambda x: d[x]['거래량'])
print(time() - t)
def dd():
t = time()
c.execute(f'select 종목코드 from {table} where cast(거래량 as decimal) > 1000 order by cast(거래량 as decimal)').fetchall()
print(time() - t)
def aa2():
t = time()
[k for k, v in d.items() if Decimal(v['종가']) > deci]
print(time() - t)
def bb2():
t = time()
c.execute(f'select 종목코드 from {table} where cast(종가 as decimal) > 1000').fetchall()
print(time() - t)
def cc2():
t = time()
sorted([k for k, v in d.items() if Decimal(v['종가']) > deci], key=lambda x: d[x]['거래량'])
print(time() - t)
def dd2():
t = time()
c.execute(f'select 종목코드 from {table} where cast(종가 as decimal) > 1000 order by cast(거래량 as decimal)').fetchall()
print(time() - t)
def aa3():
t = time()
list(filter(lambda x: d[x]['거래량'] > deci, d))
print(time() - t)
def bb3():
t = time()
c.execute(f'select 종목코드 from {table} where cast(종가 as decimal) > 1000').fetchall()
print(time() - t)
def cc3():
t = time()
sorted(list(filter(lambda x: d[x]['거래량'] > deci, d)), key=lambda x: d[x]['거래량'])
print(time() - t)
def dd3():
t = time()
c.execute(f'select 종목코드 from {table} where cast(종가 as decimal) > 1000 order by cast(거래량 as decimal)').fetchall()
print(time() - t)
def aaa():
t = time()
[k for k, v in d.items() if v['거래량'] > deci and Decimal(v['종가']) > deci]
print(time() - t)
def bbb():
t = time()
c.execute(f'select 종목코드 from {table} where cast(거래량 as decimal) > 1000 and cast(종가 as decimal) > 1000').fetchall()
print(time() - t)
def ccc():
t = time()
sorted([k for k, v in d.items() if v['거래량'] > deci and Decimal(v['종가']) > deci], key=lambda x: d[x]['거래량'])
print(time() - t)
def ddd():
t = time()
c.execute(f'select 종목코드 from {table} where cast(거래량 as decimal) > 1000 and cast(종가 as decimal) > 1000 order by cast(거래량 as decimal)').fetchall()
print(time() - t)
for i in [aa, bb, cc, dd,
aa2, bb2, cc2, dd2,
aa3, bb3, cc3, dd3,
aaa, bbb, ccc, ddd]:
print(i, end=' / ')
i()
결과
0.033998966217041016
len(d)=2784
d['005930']={'종목코드': '005930', '종목명': '삼성전자', '시가': '73000', '고가': '74100', '저가': '72800', '종가': '73100', '거래량': Decimal('13038939')}
<function aa at 0x00000198FCFCCF40> / 0.0
<function bb at 0x00000198FCFCD120> / 0.0029993057250976562
<function cc at 0x00000198FCFCCFE0> / 0.002000093460083008
<function dd at 0x00000198FCFCD1C0> / 0.003998994827270508
<function aa2 at 0x00000198FCFCD260> / 0.0029993057250976562
<function bb2 at 0x00000198FCFCD080> / 0.002000093460083008
<function cc2 at 0x00000198FCFCE5C0> / 0.0039997100830078125
<function dd2 at 0x00000198FCF58B80> / 0.003000020980834961
<function aa3 at 0x00000198FCFC77E0> / 0.0010001659393310547
<function bb3 at 0x00000198FCFC47C0> / 0.004000186920166016
<function cc3 at 0x00000198FCFC4C20> / 0.002000093460083008
<function dd3 at 0x00000198FCF6CB80> / 0.0029990673065185547
<function aaa at 0x00000198FCF6DB20> / 0.002000093460083008
<function bbb at 0x00000198FCF6DBC0> / 0.0019996166229248047
<function ccc at 0x00000198FCF6FF60> / 0.002000093460083008
<function ddd at 0x00000198FCF6E020> / 0.0019996166229248047
결론
단순 데이터 조회는 그냥 파이썬에서 해결하는게 더 빠를 수 있지만, 복합적인 조건을 적용하는 경우 sqlite를 사용하는게 더 빠르다.
설명
예제 코드는 정말 단순한 코드다. 각 함수별로 특정 작업을 하고, 경과 시간을 출력한다.
aa~dd는 decimal 객체를 기준으로 비교하며, aa2~dd2은 str 요소를 decimal 객체로 변환한 다음 비교한다.
aa3~dd3는 비교자(>, <, =)가 아닌 filter 함수를 사용하고, aaa~ddd는 2개의 요소를 비교한다.
작성한 코드들은 대충 다음과 같은 공통점을 갖는다.
aa => 단순 비교(list), bb => 단순 비교(sqlite), cc => 단순 비교 + 정렬(list), dd => 단순 비교 + 정렬(sqlite)
사용한 데이터는 개인적으로 가져온 주가 데이터로, 대충 종목코드, 종목명, 시가, 저가, 고가, 종가, 거래량 데이터가 있다.
데이터의 수는 코드와 결과에서 볼 수 있듯이 3천개가 약간 안된다.
다음은 각 조건별 결과를 초보자의 입장에서 대충 정리만 해둔 것이다.
aa~dd
dict의 요소를 decimal로 변환한 상태에서 비교하는 것은 sqlite를 사용하는게 더 느렸다.
파이써닉([i for i in list])한 코드를 사용하는 것은 그냥 for 루프를 사용하는 것과 큰 차이가 없다고 생각했었는데, 작업 시간이 0초가 나와서 살짝 놀랐다.
aa2~dd2
dict의 str 요소를 decimal로 변환해가며 비교하는 것은 sqlite가 미묘하게 더 빨랐다
aa3~dd3
이미 변환된 데이터를 비교하는 것은 sqlite가 더 빨랐다.
다만, filter를 사용하는 것이 그냥 루프를 돌려서 비교하는 것보다는 느렸다.
aaa~ddd
비교자를 2개 넣었다. LIST에서는 decimal로 변환된 것과 str을, sqlite에서는 2개 요소를 모두 decimal로 변환해서 비교했다.
이 작업은 sqlite가 더 빨랐는데, 흥미로운 점은 1개의 요소만 비교했을 때보다 작업이 더 빨라졌다는 것이다.