프로그램하는 방법을 스스로 가르치려고, 나는 주문한 모든 책을 표시하기 위해 작은 웹 응용 프로그램 (Flask, SQLAlchemy, Jijna)을 만들고 있습니다. 아마존에서.다 - 대 - 다 관계의 쿼리 속도 향상
"barest bones"가능한 방법으로, 나는 http://pinboard.in을 복제하는 법을 배우려고합니다. 그것은 내 모범입니다. Maciej Cegłowski는 똑바로 G입니다 ... 그의 사이트가 어떻게 그렇게 빨리 움직이는 지 전혀 알지 못합니다. 160 개의 북마크 항목을로드 할 수 있습니다. 모두 관련 태그 -in, dunno, 500 ms? ... 나는 왜 내가 끔찍하고 끔찍한 잘못을 저지르고 있는지를 아는 이유입니다. (내가 할 수 있다면, 그냥 교사에게 가르쳐 줄께.)
어쨌든 내 books
클래스와 내 tag
클래스 사이에 다 대다 관계를 만들었으므로 (1) book
을 클릭하고 tags
과 (2) tag
을 클릭하고 관련 도서를 모두 확인하십시오.
assoc = db.Table('assoc',
db.Column('book_id', db.Integer, db.ForeignKey('books.book_id')),
db.Column('tag_id', db.Integer, db.ForeignKey('tags.tag_id'))
)
class Book(db.Model):
__tablename__ = 'books'
book_id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(120), unique=True)
auth = db.Column(db.String(120), unique=True)
comment = db.Column(db.String(120), unique=True)
date_read = db.Column(db.DateTime)
era = db.Column(db.String(36))
url = db.Column(db.String(120))
notable = db.Column(db.String(1))
tagged = db.relationship('Tag', secondary=assoc, backref=db.backref('thebooks',lazy='dynamic'))
def __init__(self, title, auth, comment, date_read, url, notable):
self.title = title
self.auth = auth
self.comment = comment
self.date_read = date_read
self.era = era
self.url = url
self.notable = notable
class Tag(db.Model):
__tablename__ = 'tags'
tag_id = db.Column(db.Integer, primary_key=True)
tag_name = db.Column(db.String(120))
문제
나는 books
테이블을 통해 반복하는 경우에만 (~ :
여기 Entity relationship diagram
두 클래스 사이의 관계에 대한 코드입니다 : 여기 내 테이블 아키텍처 400 행) 쿼리가 실행되고 번개 속도로 브라우저로 렌더링됩니다. 문제 없습니다. 그러나, 나는 어떤을 보여주고 싶은 책과 관련된 모든 태그, 나는 for loop
를 중첩하여 코드를 변경하는 경우
{% for i in book_query %}
<li>
{{i.notable}}{{i.notable}}
<a href="{{i.url}}">{{i.title}}</a>, {{i.auth}}
<a href="/era/{{i.era}}">{{i.era}}</a> {{i.date_read}}
{% if i.comment %}
<p>{{i.comment}}</p>
{% else %}
<!-- print nothing -->
{% endif %}
</li>
{% endfor %}
는 다음과 같이
{% for i in book_query %}
<li>
{{i.notable}}{{i.notable}}
<a href="{{i.url}}">{{i.title}}</a>, {{i.auth}}
<a href="/era/{{i.era}}">{{i.era}}</a>
{% for ii in i.tagged %}
<a href="/tag/{{ii.tag_name}}">{{ii.tag_name}}</a>
{% endfor %}
{{i.date_read}}
{% if i.comment %}
<p>{{i.comment}}</p>
{% else %}
<!-- print nothing -->
{% endif %}
</li>
{% endfor %}
쿼리 크게 아래로 속도가 느려 (약 20 초 소요). 내 코드는 book
테이블의 모든 행에 대해 내 코드가 전체assoc
테이블 (즉, "전체 테이블 스캔")을 반복하기 때문에 이러한 현상이 발생합니다. 분명히
("제가 생각하는 것은 일어나고있다"또는,)
토론, 나는 완전한 멍청한 놈 들려요은 2 ~ 3 개월 동안 프로그래밍 된입니다. 그것은 단지 일을 시작하게 동기를 부여하지만, 내가 따라갈 때 채우기 위해 노력하고있는 지식 기반에는 큰 차이가 있다는 것을 알게됩니다. 오른쪽이 박쥐
, 나는 그것이 각각의 새로운 책, 코드가 전체 연관 테이블을 통해 반복되는 것을 매우 비효율적 있음을 알 수 있습니다 (즉 나는 그것이 믿는, 무슨 일이 일어나고 있는지 참 인 경우). 나는 내가 book with book_id == 1
에 대한 모든 태그를 검색 한 후에 다시 book_id == 1
assoc
테이블의 행을 "확인"하는 방식으로 assoc
테이블을 클러스터링 (?)하거나 정렬 (?)해야한다고 생각합니다.즉
가, 내가 무슨 일이 일어나고 생각하면이 (computerspeak에)입니다 :
- 오, 그는
books
테이블에book_id == 1
와 책이 - 좋아 태그 된 방법을 알고 싶어 나를 보자
assoc
테이블로 이동 - 행 번호 1 ...
assoc
테이블의book_id
은1
과 동일합니까? - 좋습니다. Row # 1에 대해
tag_id
은 무엇입니까? ... [컴퓨터가tag
테이블로 이동하여tag_name
테이블을 반환하고 브라우저로 반환] - 행 번호 2 ...
book_id
은assoc
테이블은1
과 동일합니까? - 오, 안돼, 그렇지 않다 ... 알았어, 행 # 3으로 가자.
- 흠. 내 프로그래머가 어리 석고이 테이블을 어떤 식 으로든 정렬하거나 색인을 만들지 않았기 때문에 나는 아마도 거기 더 이상있을 때 우리는
books table
컴퓨터에서book_id == 2
에 도착하면, 다음 ...book_id == 1
을 찾고 전체assoc
테이블을 통해
을 가야하는 것은 정말 미친 가져옵니다
- 좋아, 그는 함께가는 모든 태그를 알고 싶어한다.
book_id == 2
- 좋아, 나는 이미 하나를 확인하지 않았다 ... 나 ...을
assoc
테이블 - 행 # 1로 이동 잠깐만 보자? 이런 젠장 # t, 나는 이것을 다시해야만한다 ??
- 젠장 ... 좋아요 ... 행 번호 1 ...은
book_id == 2
입니까? (나는 그것이 아니라는 것을 알고!하지만 내가 프로그래머가 둠 - 둠 때문에 어쨌든 확인해야 ...)
질문
그래서 질문 (수는 I (1) 종류입니까?) 또는 클러스터 (?) assoc
테이블을 통해 "지능형"순회를 보장하는 어떤 방식 으로든 assoc
테이블을 사용하거나, 제 친구가 제안한대로 I (2)가 "좋은 SQL 쿼리 작성 방법 배우기"를 수행합니까? 모든 입력에 대한
감사를