Closed 5minho closed 6 years ago
let config = FTS4Config()
.column(Virtual.Column.id, [.unindexed])
.column(Virtual.Column.title)
.column(Virtual.Column.content)
.column(Virtual.Column.createdDate, [.unindexed])
.column(Virtual.Column.modifiedDate, [.unindexed])
self.dbManager.createTable(statement: Virtual.table.create(.FTS4(config)))
index를 유지할 컬럼을 설정해주자!! title 과 content 검색을 의도 했는데 검색 키워드와 전혀 상관없는 꿈들이 나와서 가상테이블을 위처럼 생성해주니 의도한 바로 검색결과가 나왔다.
Like Query 와 전문탐색 중 어느것이 더 빠른가를 보기 위해 테스트를 했다.
self.measure {
let searchTexts = ["내용", "423", "꿈", "42", "번", "번째", "13", "31"]
for searchText in searchTexts {
DreamDataStore.shared.filter(searchText) // like %searchText% 사용
DreamDataStore.shared.filteredDreams.forEach { dream in
if let content = dream.content?.lowercased(),
let title = dream.title?.lowercased() {
let lowerSearchText = searchText.lowercased()
if content.contains(lowerSearchText) == false && title.contains(lowerSearchText) == false {
XCTFail()
}
}
}
}
}
self.measure {
let searchTexts = ["내용", "423", "꿈", "42", "번", "번째", "13", "31"]
for searchText in searchTexts {
DreamDataStore.shared.ftsFilter(searchText) // 전문탐색 사용
DreamDataStore.shared.filteredDreams.forEach { dream in
if let content = dream.content?.lowercased(),
let title = dream.title?.lowercased() {
let lowerSearchText = searchText.lowercased()
if content.contains(lowerSearchText) == false && title.contains(lowerSearchText) == false {
XCTFail()
}
}
}
}
}
이런식으로 searchText의 내용을 바꿔가면서 테스트를 해봤는데 결과는 like 쿼리가 더 빨랐다. 문자열을 다 비슷하게 저장해서 검색한점??? 아직 문자열의 개수가 작은점??? 아니면 테스트코드가 미숙해서??? 아직 정확한 이유가 생각하지 않아서 좀 더 조사해봐야겠다.
func testLotsOfDateInsert() {
var date = Date(timeIntervalSince1970: 0)
let current = Date()
var i = 0
while date.timeIntervalSince1970 < current.timeIntervalSince1970 {
let dream = Dream( title: "\(i + 1) 번째 꿈 제목",
content: "\(i + 1) 번째 꿈의 내용",
createdDate: date,
modifiedDate: nil)
date.addTimeInterval(43200)
i += 1
DreamDataStore.shared.insert(dream: dream)
}
}
위의 조사를 하기 위해 이런식으로 데이터를 삽입 했고 1970년 부터 오늘까지 하루에 2번씩 꿈을 저장 했을때 상황입니다. 테이블마다 문자열의 패턴이 일정해서 저런 결과가 나올수도 있으니 좀더 다양하게 문자열을 저장해서 검사해 볼 것!
꿈 검색 기능을 구현하면서 처음에는 Like Query를 생각하고 단순히 이런 코드를 작성했다.
처음에는 잘 작동하는거 처럼 보였으나 꿈 데이터를 몇 만개씩 늘리니 슬슬 검색 속도가 줄기 시작했다. 해결책으로는 Sqlite 에 Full test search (전문검색) 이라는 것이 있었고 Like 쿼리는 해당 문자열을 찾기 위해 테이블 전체를 Full-Scan 하고 전문검색 같은 경우는 문자열을 인덱싱해서 B-tree로 유지해 빠른 문자열 검색을 지원한다고 한다.
sqlite 에서는 가상테이블을 통해 전문검색을 지원한다.
우리 앱은 DB 테이블이 많지 않다. 그래서 빠른 검색을 위해 가상테이블로 문자열 인덱스를 유지해도 메모리 부분의 이슈는 없을거라고 판단되어 전문검색을 사용하기로 했다.