Ето няколко неща, които бих опитал, в ред на нарастваща трудност:
(по-лесно) - Уверете се, че имате правилния индекс на покритие
CREATE INDEX ix_temp ON relations (relation_title, object_title);
Това би трябвало да максимизира perf предвид съществуващата ви схема, тъй като (освен ако вашата версия на оптимизатора на mySQL не е наистина глупава!) ще минимизира количеството I/O, необходими за задоволяване на вашата заявка (за разлика от това, ако индексът е в обратния ред, където целият индекс трябва да бъде сканиран) и ще покрие заявката, така че няма да ви се налага да докосвате клъстерирания индекс.
(малко по-трудно) – уверете се, че полетата на varchar са възможно най-малки
Едно от предизвикателствата на perf с varchar индекси в MySQL е, че при обработка на заявка пълният деклариран размер на полето ще бъде изтеглен в RAM. Така че, ако имате varchar(256), но използвате само 4 символа, вие все още плащате за 256-байтово използване на RAM, докато заявката се обработва. Оу! Така че, ако можете лесно да свиете ограниченията на varchar, това трябва да ускори вашите заявки.
(по-трудно) - нормализиране
30% от вашите редове със стойност на един низ е ясен вик за нормализиране в друга таблица, така че да не дублирате низове милиони пъти. Помислете за нормализиране в три таблици и използване на целочислени идентификатори, за да ги присъедините.
В някои случаи можете да нормализирате под кориците и да скриете нормализирането с изгледи, които съвпадат с името на текущата таблица... тогава трябва само да накарате вашите INSERT/UPDATE/DELETE заявки да осъзнаят нормализирането, но можете да оставите вашите SELECTs на мира .
(най-трудно) – Хеширайте колоните си с низове и индексирайте хешовете
Ако нормализирането означава промяна на твърде много код, но можете да промените малко схемата си, може да помислите за създаване на 128-битови хешове за колоните с низове (използвайки MD5 функция ). В този случай (за разлика от нормализирането) не е нужно да променяте всичките си заявки, а само INSERT и някои от SELECT. Както и да е, ще искате да хеширате своите низови полета и след това да създадете индекс върху хешовете, напр.
CREATE INDEX ix_temp ON relations (relation_title_hash, object_title_hash);
Обърнете внимание, че ще трябва да поиграете с SELECT, за да сте сигурни, че извършвате изчислението чрез хеш индекса, а не изтегляте клъстерирания индекс (изисква се за разрешаване на действителната текстова стойност на object_title, за да удовлетворите заявката).
Също така, ако relation_title има малък размер на varchar, но заглавието на обекта има дълъг размер, тогава можете потенциално да хеширате само object_title и да създадете индекса на (relation_title, object_title_hash)
.
Имайте предвид, че това решение помага само ако едно или и двете от тези полета са много дълги спрямо размера на хешовете.
Също така имайте предвид, че има интересни въздействия за чувствителност към малки и големи букви/съпоставяне от хеширане, тъй като хешът на низ с малки букви не е същият като хешът на главен. Така че ще трябва да се уверите, че прилагате канонизация към низовете, преди да ги хеширате - с други думи, хеширайте само с малки букви, ако сте в DB, независимо от главните букви. Може също да искате да отрежете интервалите от началото или края, в зависимост от това как вашата DB обработва начални/завършващи интервали.