Първо, за справяне с конкретните въпроси, които повдигате:
-
Както е документирано под
CREATE INDEX
Синтаксис :Ето защо, преди дори да помислите за
HASH
индексиране, трябва да се знае, че е само достъпно вMEMORY
иNDB
машини за съхранение:така че може дори да не е опция за вас.Освен това, имайте предвид, че индексира комбинации от
ID
иLookup
сам по себе си може да не е оптимален, тъй като вашиятWHERE
предикатът също филтрира върхуtablea.Elg_IDpart1
иtableb.IDpart1
—може да се възползвате и от индексирането на тези колони. -
При условие, че желаните типове индекси се поддържат от механизма за съхранение, можете да ги смесвате, както сметнете за добре.
-
Можете да използвате индекс намек за да принуди MySQL да използва индекси, различни от тези, които оптимизаторът иначе би избрал.
-
Това е обикновено достатъчно умен, но не винаги. В този случай обаче той вероятно е определил, че кардиналността на индексите е такава, че е по-добре да използва тези, които е избрал.
Сега, в зависимост от версията на MySQL, която използвате, таблиците, получени от подзаявки, може да нямат никакви индекси върху тях, които могат да се използват за по-нататъшна обработка:следователно присъединяването с b
може да изисква пълно сканиране на тази извлечена таблица (няма достатъчно информация във вашия въпрос, за да определите колко точно проблем може да бъде това, но schema1.tableb
наличието на 1,5 милиона записа предполага, че може да е значителен фактор).
Вижте Оптимизация на подзаявки за повече информация.
Следователно трябва да се опитаме да избегнем използването на производни таблици, ако изобщо е възможно. В този случай изглежда няма никаква цел за получената ви таблица, тъй като човек може просто да се присъедини към schema1.tablea
и schema1.tableb
директно:
UPDATE schema1.tablea a
JOIN schema1.tableb b USING (ID, Lookup)
SET a.Elg_IDpart1 = b.IDpart1,
a.Elg_IDpart2 = b.IDpart2
WHERE a.Elg_IDpart1 IS NULL
AND a.ID IS NOT NULL
AND b.IDpart1 IS NOT NULL
AND b.Lookup IS NOT NULL
ORDER BY ID, Lookup
Единственото нещо, което е загубено, е филтърът за DISTINCT
записи, но дублиращите се записи просто ще (опитват) да презапишат актуализираните стойности със същите стойности отново – което няма да има ефект, но може да се окаже много скъпо (особено при толкова много записи в тази таблица).
Използването на ORDER BY
в извлечената таблица беше безсмислено, тъй като не можеше да се разчита, че ще постигне някакъв конкретен ред на UPDATE
, докато в тази преработена версия ще гарантира, че всички актуализации, които презаписват предишни, се извършват в посочения ред:но необходимо ли е това? Може би може да бъде премахнат и запазен при всяка операция по сортиране.
Човек трябва да провери предикатите в WHERE
клауза:всички ли са необходими (NOT NULL
проверява a.ID
и b.Lookup
, например, са излишни, като се има предвид, че всеки такъв NULL
записите ще бъдат елиминирани чрез JOIN
предикат)?
Като цяло това ни оставя с:
UPDATE schema1.tablea a
JOIN schema1.tableb b USING (ID, Lookup)
SET a.Elg_IDpart1 = b.IDpart1,
a.Elg_IDpart2 = b.IDpart2
WHERE a.Elg_IDpart1 IS NULL
AND b.IDpart1 IS NOT NULL
Само ако производителността все още е незадоволителна, трябва да се погледне допълнително индексирането. Съответни колони (т.е. тези, използвани в JOIN
). и WHERE
предикати) индексирани? Избират ли се индексите за използване от MySQL (имайте предвид, че той може да използва само един индекс на таблица за справки:за тестване и на JOIN
предикат и предикати на филтъра:може би имате нужда от подходящ съставен индекс)? Проверете плана за изпълнение на заявката, като използвате EXPLAIN
за да проучи допълнително такива проблеми.