Oto, co zrobiłem i skróciłem całkowity czas wykonania o współczynnik 10.
Z planu wykonania mojego oryginalnego zapytania zdałem sobie sprawę, że używało ono sortowania plików do sortowania wszystkich wyników i ignorowania indeksów. To trochę marnotrawstwo.
Moja testowa baza danych:5 mln rekordów, rozmiar 20 GB. struktura tabeli taka sama jak w pytaniu
Zamiast pobierać blobCol bezpośrednio w pierwszym zapytaniu, najpierw otrzymuję wartość 'name' na początku każdej strony. Uruchom to zapytanie w nieskończoność, aż zwróci 0 wyników. Za każdym razem dodaj wynik do listy
SELECT name
FROM my_table
where id = <anyId> // I use the id column for partitioning so I need this here
order by name
limit <pageSize * pageNumber>, 1
Numer strony sinus nie jest wcześniej znany, zacznij od wartości 0 i zwiększaj, aż zapytanie zwróci wartość null. Możesz także zrobić select count(*), ale samo to może zająć dużo czasu i nie pomoże niczego zoptymalizować. Każde zapytanie trwało około 2 sekund, gdy numer strony przekroczył ~60.
Dla mnie rozmiar strony wynosił 5000, więc otrzymałem listę ciągów „nazwa” na pozycjach 0, 5001, 10001, 15001 i tak dalej. Okazało się, że liczba stron wynosi 1000, a przechowywanie listy 1000 wyników w pamięci nie jest drogie.
Teraz przejrzyj listę i uruchom to zapytanie
SELECT blobCol
FROM my_table
where name >= <pageHeader>
and name < <nextPageHeader>
and city="<any string>"
and id= 1
Uruchomi się to N razy, gdzie N =rozmiar listy otrzymanej wcześniej. Ponieważ „nazwa” jest kluczem podstawowym col, a „miasto” jest również indeksowane, EXPLAIN pokazuje, że to obliczenie jest wykonywane w pamięci przy użyciu indeksu.
Teraz wykonanie każdego zapytania zajmuje 1 sekundę, zamiast pierwotnych 30-40. Łącząc czas wstępnego przetwarzania 2 sekund na stronę, całkowity czas na stronę wynosi 3-4 sekundy zamiast 30-40.
Jeśli ktoś ma lepsze rozwiązanie lub jeśli coś jest rażąco nie tak z tym, daj mi znać