테이블의 열 수가 극적으로 SQLAlchemy의 성능에 영향을 줍니까?
잘 힘든 일 이잖아, 그것은 아마도 동일한 인터페이스를 사용하는 동안 다른 DB 엔진과 상호 작용하는 방법에 지나지이없는, 실제로 sqlalchemy
다음,이 경우 기본 SQL 엔진, MySQL
에 더 의존 .
SQLAlchemy는 응용 프로그램 개발자에게 SQL의 강력 함과 유연성을 제공하는 Python SQL 툴킷과 Object Relational Mapper입니다.
간단하고 Python 도메인 언어에 맞게 효율적이고 고성능 데이터베이스 액세스를 위해 설계된 잘 알려진 엔터프라이즈 수준의 지속성 패턴 모음을 제공합니다.
내가 틀릴 수도 있지만 표준 SQL
을 사용하여 벤치마킹을 시도해 볼 수 있습니다. 나는 실제로 몇 가지 테스트를 실행
...
import timeit
setup = """
from sqlalchemy import create_engine, MetaData, select, Table, Column
from sqlalchemy.dialects.sqlite import BOOLEAN, SMALLINT, VARCHAR
engine = create_engine('sqlite://', echo = False)
metadata = MetaData()
conn = engine.connect()
columns = []
for i in xrange(100):
columns.append(Column('c%d' % i, VARCHAR(1), nullable = False, server_default = '0'))
columns.append(Column('d%d' % i, VARCHAR(2), nullable = False, server_default = '00'))
user = Table('user', metadata, *columns)
user.create(engine)
conn.execute(user.insert(), [{}] * 4000)
user2 = Table('user2', metadata, Column('c0', VARCHAR(100), nullable = False, server_default = '0' * 100), \
Column('d0', VARCHAR(200), nullable = False, server_default = '0' * 200))
user2.create(engine)
conn.execute(user2.insert(), [{}] * 4000)
"""
many_columns = """
s1 = select([user]).compile(engine)
result = conn.execute(s1).fetchall()
"""
two_columns = """
s2 = select([user2]).compile(engine)
result = conn.execute(s2).fetchall()
"""
raw_many_columns = "res = conn.execute('SELECT * FROM user').fetchall()"
raw_two_columns = "res = conn.execute('SELECT * FROM user2').fetchall()"
timeit.Timer(two_columns, setup).timeit(number = 1)
timeit.Timer(raw_two_columns, setup).timeit(number = 1)
timeit.Timer(many_columns, setup).timeit(number = 1)
timeit.Timer(raw_many_columns, setup).timeit(number = 1)
>>> timeit.Timer(two_columns, setup).timeit(number = 1)
0.010751008987426758
>>> timeit.Timer(raw_two_columns, setup).timeit(number = 1)
0.0099620819091796875
>>> timeit.Timer(many_columns, setup).timeit(number = 1)
0.23563408851623535
>>> timeit.Timer(raw_many_columns, setup).timeit(number = 1)
0.21881699562072754
내가이 찾을 않았다 가지 흥미로운 그는 테스트 max
사용하지만했다
http://www.mysqlperformanceblog.com/2009/09/28/how-number-of-columns-affects-performance/
...
난 정말 sqlalchemy 사랑해, 그래서 비단뱀 자신의 sqlite3 모듈을 사용하여 그것을 비교하기로 결정했습니다
import timeit
setup = """
import sqlite3
conn = sqlite3.connect(':memory:')
c = conn.cursor()
c.execute('CREATE TABLE user (%s)' %\
("".join(("c%i VARCHAR(1) DEFAULT '0' NOT NULL, d%i VARCHAR(2) DEFAULT '00' NOT NULL," % (index, index) for index in xrange(99))) +\
"c99 VARCHAR(1) DEFAULT '0' NOT NULL, d99 VARCHAR(2) DEFAULT '0' NOT NULL"))
c.execute("CREATE TABLE user2 (c0 VARCHAR(100) DEFAULT '%s' NOT NULL, d0 VARCHAR(200) DEFAULT '%s' NOT NULL)" % ('0'* 100, '0'*200))
conn.commit()
c.executemany('INSERT INTO user VALUES (%s)' % ('?,' * 199 + '?'), [('0',) * 200] * 4000)
c.executemany('INSERT INTO user2 VALUES (?,?)', [('0'*100, '0'*200)] * 4000)
conn.commit()
"""
many_columns = """
r = c.execute('SELECT * FROM user')
all = r.fetchall()
"""
two_columns = """
r2 = c.execute('SELECT * FROM user2')
all = r2.fetchall()
"""
timeit.Timer(many_columns, setup).timeit(number = 1)
timeit.Timer(two_columns, setup).timeit(number = 1)
>>> timeit.Timer(many_columns, setup).timeit(number = 1)
0.21009302139282227
>>> timeit.Timer(two_columns, setup).timeit(number = 1)
0.0083379745483398438
같은 결과가 나왔으므로 데이터베이스 구현이 sqlalchemy
이 아니라고 생각합니다. sqlite3를 모듈
DEFAULT의 INSERT
import timeit
setup = """
from sqlalchemy import create_engine, MetaData, select, Table, Column
from sqlalchemy.dialects.sqlite import BOOLEAN, SMALLINT, VARCHAR
engine = create_engine('sqlite://', echo = False)
metadata = MetaData()
conn = engine.connect()
columns = []
for i in xrange(100):
columns.append(Column('c%d' % i, VARCHAR(1), nullable = False, server_default = '0'))
columns.append(Column('d%d' % i, VARCHAR(2), nullable = False, server_default = '00'))
user = Table('user', metadata, *columns)
user.create(engine)
user2 = Table('user2', metadata, Column('c0', VARCHAR(100), nullable = False, server_default = '0' * 100), \
Column('d0', VARCHAR(200), nullable = False, server_default = '0' * 200))
user2.create(engine)
"""
many_columns = """
conn.execute(user.insert(), [{}] * 4000)
"""
two_columns = """
conn.execute(user2.insert(), [{}] * 4000)
"""
>>> timeit.Timer(two_columns, setup).timeit(number = 1)
0.017949104309082031
>>> timeit.Timer(many_columns, setup).timeit(number = 1)
0.047809123992919922
테스트.
import timeit
setup = """
import sqlite3
conn = sqlite3.connect(':memory:')
c = conn.cursor()
c.execute('CREATE TABLE user (%s)' %\
("".join(("c%i VARCHAR(1) DEFAULT '0' NOT NULL, d%i VARCHAR(2) DEFAULT '00' NOT NULL," % (index, index) for index in xrange(99))) +\
"c99 VARCHAR(1) DEFAULT '0' NOT NULL, d99 VARCHAR(2) DEFAULT '0' NOT NULL"))
c.execute("CREATE TABLE user2 (c0 VARCHAR(100) DEFAULT '%s' NOT NULL, d0 VARCHAR(200) DEFAULT '%s' NOT NULL)" % ('0'* 100, '0'*200))
conn.commit()
"""
many_columns = """
c.executemany('INSERT INTO user VALUES (%s)' % ('?,' * 199 + '?'), [('0', '00') * 100] * 4000)
conn.commit()
"""
two_columns = """
c.executemany('INSERT INTO user2 VALUES (?,?)', [('0'*100, '0'*200)] * 4000)
conn.commit()
"""
timeit.Timer(many_columns, setup).timeit(number = 1)
timeit.Timer(two_columns, setup).timeit(number = 1)
>>> timeit.Timer(many_columns, setup).timeit(number = 1)
0.14044189453125
>>> timeit.Timer(two_columns, setup).timeit(number = 1)
0.014360189437866211
>>>
훌륭한 의견을 보내 주셔서 감사합니다. 실제로 관련 질문 [int 및 binary 삽입 속도] (http://stackoverflow.com/questions/11388729/the-insert-speed-of-int-and-binary)를 물었습니다. 필자는 동일한 테이블에서 sql을 사용하여 삽입 속도를 테스트 한 결과 더 많은 열이있는 테이블에 대해 삽입 속도가 빠르다는 사실을 발견했습니다. 이상하지 않니? @ samy.vilar – heller
재미있는 @heller, 간단한/빈 삽입을 사용하여 간단한 간단한 테스트를했는데 채워졌지만 VARCHAR를 사용하여 어디에서나 재미있는 전환 확인을 확인했는데 two_columns가있는 위치가 더 빠르다는 것을 확인했습니다. MySQL이 할 수있는 일이 무엇인지 모르겠다. 기사에서'InooDB가 훨씬 느리다 '고 말한 적이있다. –
"[col for row in col]"와 같은 각 열의 각 열에 액세스하면 SQLAlchemy 예제는 약간의 오버 헤드가 있습니다. SQLite를 사용하면 열 유형의 데이터 프로세서 만 사용할 수 있습니다. 더구나, 당신은 여기에서 다만 핵심을 사용하게 기쁘다! ORM을 사용하면 전체 개체를로드하는 경우 오버 헤드가 훨씬 더 중요합니다. – zzzeek