728x90

실제 검색서비스가 메인이든 아니든, 실제로 코드를 짤때 DB에서 특정 데이터들을 search 하는 경우는 매우 흔하다. 

이러한 경우 일반적으로 orm query를 사용할테지만, 때때로는 orm 말고도 Raw SQL query를 사용하는 경우가 있을 것이다. 

그리고 각 경우 내에서도 실제 DB를 검색하기 위해 사용하는 쿼리문도 다양하므로 때에따라 적절히 선택해야 한다.

따라서 어떠한 경우에 어느 방법을 쓰는 것을 좋을 지 간단하게 정리해보려한다. 

 

우선은 ORM과 Raw SQL 자체를 비교해보자.

1. ORM vs Raw SQL 

참고글 리스트

https://news.ycombinator.com/item?id=16809620 

https://itinerant.tistory.com/27

https://docs.djangoproject.com/en/3.2/topics/db/sql/

https://stackoverflow.com/questions/58947356/raw-sql-vs-orm-if-i-already-know-sql

 

Raw SQL 

속도면에서 빠름(SQL has better performance) / 당연히 ORM이 가지는 단점이 rawSQL의 장점일것

 

ORM

유지보수, 재사용성에 용이

filter 조건이 많아지거나 , JOIN 관계가 많아지면 쿼리가 복잡해지고 오히려 가독성이 떨어지게됨 / DB 유형을 바꾸더라도 코드 상의 변화는 없다.(PostgresSQL -> MySQL같은)

 

본론으로 들어가서, 다른 경우가 아닌 db를 search를 하려할 때, 실제로 orm과 sql 모두 구현할수 있는 방법이 있다.

orm : contains , in

rawSQL : Like , fulltext search(match / against)

그렇다면 위의 경우와는 크게 상관이 없을 수있는(ORM을 쓰던 Sql 쿼리를 쓰던 크게 복잡하지 않다.) search를 하려할 때는 어떤 방법이 더 효율적일까?(django 공식문서 )

The field lookups that equate to LIKE SQL statements (iexact, contains, icontains, startswith, istartswith, endswith and iendswith) will automatically escape the two special characters used in LIKE statements – the percent sign and the underscore. (In a LIKE statement, the percent sign signifies a multiple-character wildcard and the underscore signifies a single-character wildcard.)
This means things should work intuitively, so the abstraction doesn’t leak.

For example, to retrieve all the entries that contain a percent sign, use the percent sign as any other character:
>>> Entry.objects.filter(headline__contains='%')

Django takes care of the quoting for you; the resulting SQL will look something like this:
>>>SELECT ... WHERE headline LIKE '%\%%';
Same goes for underscores. Both percentage signs and underscores are handled for you transparently.

공식문서에서 언급한 바를 정리하면, 좀 더 정확한 search결과를 얻고 싶다면 sql LIKE statement를 사용하면 된다.

 

정리하자면,

1) 진짜 검색 기능을 구현하기 위해 db search를 하고자 할때는 sql statement를 

2) 쿼리문 작성 중, 일종의 filter 역할로 db search를 하고자 할땐 orm을 사용하는 것으로 

이해했다..(맞겠지? 좀 더 공부하고 아니라면 수정할예정)

 

그렇다면 db search 시에 sql statement에는 LIKE 만이 답일까? 당연히 아니다.

일반적으로는 LIKE가 쓰이지만, 더 고도화된 기능으로 full-text search 인덱싱이 있다.

이와 관련해서는 좀 더 공부해서 자세하게 정리해볼 예정이며 여기선 대략적으로만 알아보려 한다.

 

1) LIKE는 어느정도 사용해보면 알겠지만, 특정 검색어가 포함된 모든 data를 추출한다. 따라서 누락이 없지만 느리다

 

2) 이에 대한 대체가 full-text 인덱싱이다. 말그대로 db 인덱싱을 활용한 방법인데, 사용과 코드예시는 해당 블로그를 보면 쉽게 이해할 수 있다. 즉 인덱싱이 걸려있는 모델 필드들 중에서, 내가 검색을 원하는 조합으로 새로은 인덱스를 생성하고, 거기서 search 하는 것이다.

당연히 속도면에서 빠르고 효율적이겠지만, 인덱스가 바로바로 생성되지 않아서 검색이 누락되는 경우가 있다.

이러한 경우 블로그에 언급된 것처럼 인덱싱을 재생성해주면된다.

https://interconnection.tistory.com/95

-> 오늘 겪었던 문제였다. 코드나 정보에는 아무런 문제가 없는데 실제 서비스에서 일부 데이터가 검색에서 누락되었다. 

원인을 파악하기 가장 힘들었던 이유는, 실제 db로 sql을 적어주었을 때는 데이터가 누락이 없었는데, 서비스 api에서는 누락이 되었던 것이다. 이는 실제 서비스에서는 main db만 쓰는것이 아니라 복제db도 쓸 것이고, 인덱싱이 모든 복제db에 적용되지 않았기 때문에 발생한 것이었다.

 

오늘 겪었던 문제로 실제 검색이 얼마나 복잡한지....

인덱싱이 얼마나 중요한지...

검색이 메인인 서비스들에서 elasticsearch를 왜 도입하는지 어느정도 이해할 수 있었다.

하지만 오늘 배운걸 정리하다보니 django orm으로도 full-text search를 적용할 수있다는 글을 보고 해당 부분에 대해서는 확실히 좀 더 자세하게 알아봐야겠다고 느꼈다!

 

728x90

'TIL(Today I Learned)' 카테고리의 다른 글

TIL_0211_Django-Ninja  (0) 2022.02.11
TIL_0211_HTTP HOST ERROR  (0) 2022.02.11
TIL_0826_python requests post json VS data  (0) 2021.08.29
TIL_0819_spark VS 맵리듀스 hadoop  (0) 2021.08.19
TIL_210811_AWS IAM MFA 권한 허용  (0) 2021.08.11

+ Recent posts