2014-01-08 2 views
3

Я довольно небрежен с базами данных, не может получить эту работу с соединениями, и я даже не уверен, что будет быстрее ...Как оптимизировать эту операцию БД?

DELETE FROM atable 
WHERE btable_id IN (SELECT id 
        FROM btable 
        WHERE param > 2) 
     AND ctable_id IN (SELECT id 
         FROM ctable 
         WHERE (someblob LIKE '%_ID1_%' 
            OR someblob LIKE '%_ID2_%')) 

ATable содержит ~ 19M строк, это будет удалить ~ 3M от этого. На данный момент я могу выполнить запрос только с LIMIT 100000, и я не хочу сидеть здесь с phpmyadmin весь день, потому что каждое удаление (из 100 000 строк) работает около 1,5 минут.

Любые способы ускорить это или автоматизировать его?

MySQL 5.5

(? Как вы думаете, что это уже плохой дизайн DB если таблица содержит 20M строк)

+0

Количество строк не является мерой хорошего или плохого дизайна стола. Нормализованы ли ваши таблицы? Это будет мерой хорошего дизайна стола ... – Argeman

ответ

2

Использование EXISTS или JOIN вместо IN улучшить perfromance

Использование EXISTS:

DELETE FROM Atable A 
WHERE EXISTS (SELECT 1 FROM Btable B WHERE A.Btable_id = B.id AND B.param > 2) AND 
     EXISTS (SELECT 1 FROM Ctable C WHERE A.Ctable_id = C.id AND (C.someblob LIKE '%_ID1_%' OR C.someblob LIKE '%_ID2_%')) 

Использование JOIN:

DELETE A 
FROM Atable A 
INNER JOIN Btable B ON A.Btable_id = B.id AND B.param > 2 
INNER JOIN Ctable C WHERE A.Ctable_id = C.id AND (C.someblob LIKE '%_ID1_%' OR C.someblob LIKE '%_ID2_%') 
+0

Тот, у кого есть 'EXISTS', кажется, не улучшает ситуацию, ну, может быть, в среднем пару секунд. Моя проблема со вторым заключается в том, что я не могу указать «LIMIT», и таким образом он просто истекает. В любом случае спасибо! – Innkeeper

1

Помимо оптимизации запроса вы также могли бы взглянуть на хорошее использование индексов, так как они могут предотвратить полное сканирование таблицы.

Для BTable, например, создайте индекс для id и param.

Чтобы объяснить, почему это помогает: Если база данных должна искать значения id и param в таблице несортированным образом, база данных должна считывать ВСЕ строки. Если база данных считывает индекс, SORTED, он может искать идентификатор и параметр со сниженными затратами.

1

Прежде всего, вы должны попробовать с существующим, а не с. Это быстрее во многих случаях.

Тогда вы могли бы попытаться сделать внутреннее соединение вместо того, чтобы существовать и существует.

Пример:

delete a 
from a 
inner join b on b.id = a.tablebid 

И, наконец, если это может быть возможно (я не знаю, если у вас есть id3, идентификаторы), чтобы изменить или что-то еще. Иногда странное и сложное изменение помогает оптимизатору. случай, когда, подзапрос ...

1

Я не вижу, где простой указатель поможет много. Я хотел бы сделать:

delete from atable where id in (
    select 
     id 
    from 
     atable a 
     join btable b on a.btable_id = b.id 
     join ctable c on a.ctable_id = c.id 
    where 
     b.param > 2 
     and (
      c.someblob LIKE '%_ID1_%' 
      OR c.someblob LIKE '%_ID2_%' 
     ) 
) 

Исправление: Я предполагаю, что у вас есть индексы btable и CTABLE в идентификаторы (возможно, если они первичные ключи ...) и на b.param (если это числовое).

Смежные вопросы