I'm having issues with selecting items (between 1.000 and 4.000) via a query from my IndexedDB with Dexie in an Angular 4 application.
There are only max 20.000 items in the tables, but the selection of these takes multiple seconds (5s on Chrome 61, up to (and more) than 20s on iOS 10 & iOS 11)
Below is my service that fetches two different tables and returns an Observable via loadItems()
@Injectable()
export class ItemService {
private buildings: Dexie.Table<Building, string>;
private people: Dexie.Table<Person, string>;
private activeZip: string;
constructor(
private db: IndexeddbService,
) {
this.buildings = this.db.table('buildings');
this.people = this.db.table('people');
}
loadItems(): Observable<{
buildings: Building[],
people: Person[]
}> {
return Observable.combineLatest(
this.loadBuildings(),
this.loadPeople(),
).map(([buildings, people]) => {
return {
buildings,
people
};
});
}
private loadBuildings(): Observable<Building[]> {
return Observable.from(this.buildings.where('zip').equals(this.activeZip).toArray());
}
private loadPeople(): Observable<Person[]> {
return Observable.from(this.people.where('zip').equals(this.activeZip).toArray());
}
}
The resulting Observable is asynchronously handled with a ngrx effect, which dispatches an Action that writes the data to the state, so the component can render the information.
@Effect()
loadItems$: Observable<Action> = this.actions$
.ofType(actions.ActionTypes.LOAD_ITEMS)
.map(_ => this.itemService.setActiveZip(this.localStorageService.getActiveZip()))
.switchMap(_ => this.itemService.loadItems())
.map(items => new actions.LoadItemsSuccessAction(items))
.catch(error => Observable.of(new actions.LoadItemsFailAction(error)));
I've tried to "lazy-load" the items in chunks via https://github.com/raphinesse/dexie-batch, but the resulting batches took more than 500ms to arrive.
Where do I have a possible performance bottleneck? I've already tried to run this query outside of Angular's zones, but this did not yield and performance improvements.
With a lot of time and debugging, I've identified the following Dexie PR which breaks the IndexedDB 2.0 getAll feature in Chrome and Safari: https://github.com/dfahlander/Dexie.js/pull/579
With a revert back to Dexie 2.0.0-beta.11 performance is increased around 10x times (raw database queries via cursor to getAll went from 600-700ms back to 60ms)
Edit: Dexie 2.0.1 has been released with a correct fix for this issue