Действительно медленный запрос раньше был очень быстрым. Объяснение показывает, что строки = 1 в локальной резервной копии, но строки = 2287359 на сервере - PullRequest
1 голос
/ 18 декабря 2010

Время от времени я проверяю спам, используя "select * from posts, где post вроде"% http://%' order by id desc limit 10 ", и ищу несколько других ключевых слов. В последнее время выбор невероятно медленный.

mysql> explain select * from posts where reply like "%http://%" order by id desc limit 1;
+----+-------------+-----------+-------+---------------+---------+---------+------+---------+-------------+
| id | select_type | table     | type  | possible_keys | key     | key_len | ref  | rows    | Extra       |
+----+-------------+-----------+-------+---------------+---------+---------+------+---------+-------------+
|  1 | SIMPLE      | posts     | index | NULL          | PRIMARY | 4       | NULL | 2287347 | Using where |
+----+-------------+-----------+-------+---------------+---------+---------+------+---------+-------------+
1 row in set (0.00 sec)

На моем нетбуке с 1 Гб оперативной памяти единственное отличие состоит в том, что он показывает столбец «ROWS» равным 1. В моем нетбуке всего 1,3 миллиона сообщений. Сервер имеет как 6 ГБ оперативной памяти и быстрый процессор. Что я должен оптимизировать, чтобы он не был ужасно медленным. Недавно я добавил индекс для поиска по userId, который, я не уверен, был разумным выбором, но я добавил его на сервер резервного копирования и на производственный сервер немного раньше, чем эта проблема начала возникать. Я полагаю, это связано с тем, что из-за пропущенного твина невозможно выполнить сортировку в оперативной памяти?

Это также кажется медленным, когда я делаю что-то вроде "удалить из сообщений, где threadId = X", не знаю, если связано.

Ответы [ 4 ]

2 голосов
/ 19 декабря 2010

относительно

SELECT * FROM posts WHERE reply LIKE "%http://%" ORDER BY id DESC LIMIT 1

Из-за подстановочных знаков с обеих сторон http:// MySQL не сможет использовать индекс для reply, чтобы быстро найти то, что вы ищете. Более того, так как вы запрашиваете тот, у кого самый большой id, MySQL должен будет получить все результаты, чтобы убедиться, что у вас есть тот, у кого самый большой идентификатор.

В зависимости от того, сколько данных из таблицы posts состоит из reply, может быть целесообразно добавить составной индекс для (id, reply) и изменить запрос на что-то вроде

SELECT id FROM posts WHERE reply LIKE "%http://%" ORDER BY id DESC LIMIT 1

(который будет иметь только индексное выполнение), затем присоединитесь к таблице публикаций или извлеките сообщения, используя восстановленные id s. Если запрос имеет index only execution, а индекс помещается в память , а уже находится в памяти (из-за обычного использования или из-за преднамеренного разогрева), вы могли бы потенциально ускорить выполнение запроса.

Сказав все это, если одинаковые запросы на двух одинаковых серверах с одинаковыми данными дают разные планы выполнения и время выполнения, возможно, настало время OPTIMIZE TABLE posts обновить статистику индекса и / или дефрагментировать таблицу. Если вы недавно добавляли / удаляли индексы, все могло сбиться с пути. Более того, если данные фрагментированы, когда они вытягивают строки в порядке PRIMARY KEY, они могут перемещаться по всему диску для получения данных.

Что касается DELETE FROM posts WHERE threadId=X, то все должно быть в порядке, пока существует индекс threadId.

2 голосов
/ 18 декабря 2010

Индексы не будут использоваться, если вы начнете сравнение поиска с "%".Ваша проблема с

where reply like "%http://%"

Как подтверждается вашим объяснением, индексы не используются.Разница в скорости может быть связана с кэшированием.

1 голос
/ 18 декабря 2010

Можете ли вы написать триггер после вставки, который проверяет текст в поисках подстроки 'http://' и либо помечает текущую запись, либо записывает ее идентификатор в таблицу SPAM? Как сказал @brent, индексы не используются для поиска «содержит подстроки».

1 голос
/ 18 декабря 2010

Какие у вас индексы на ваших таблицах? Хорошее практическое правило - указывать столбцы, которые чаще всего встречаются в предложении WHERE. Если у вас нет индекса в столбце threadId, ваш последний запрос будет намного медленнее, чем если бы вы его сделали.

Ваш первый запрос (выберите * из сообщений, для которых сообщение типа '% http://%' будет медленным просто из-за "нравится" в запросе. Я бы предложил отфильтровать ваш запрос с помощью другого предложения WHERE - возможно, по дате (что с надеждой проиндексирован):

select * from posts where postdate > 'SOMEDATE' and post like '%http://%'
...