Медленный MySQL запрос. Какие-нибудь советы?

0

У меня есть следующий запрос... Он работает, но он работает очень медленно. Хотел ли кто-нибудь дать мне несколько советов по улучшению времени выполнения?

SELECT tb_clients.*, tb_clients_phone_fax.*
FROM tb_clients, tb_clients_phone_fax
WHERE tb_clients.client_id=tb_clients_phone_fax.client_id
AND MATCH (client_company,client_description,client_keywords) AGAINST ('test') > 0
AND CONCAT(client_address,' ',client_city,', ',client_state,' ',client_zip) LIKE '%brooklyn%'
LIMIT 10;

EDIT:

Вот информация о таблице:

CREATE TABLE `tb_clients` (
  `client_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `client_company` varchar(254) NOT NULL,
  `client_address` varchar(254) NOT NULL,
  `client_street` varchar(254) NOT NULL,
  `client_city` varchar(254) NOT NULL,
  `client_state` varchar(254) NOT NULL,
  `client_zip` varchar(45) NOT NULL,
  `client_email` varchar(254) NOT NULL,
  `client_website` varchar(254) NOT NULL,
  `client_description` text NOT NULL,
  `client_keywords` text NOT NULL,
  PRIMARY KEY (`client_id`) USING BTREE,
  FULLTEXT KEY `client_company` (`client_company`,`client_description`,`client_keywords`)
) ENGINE=MyISAM AUTO_INCREMENT=68347 DEFAULT CHARSET=latin1;

и

CREATE TABLE `tb_clients_phone_fax` (
  `client_phone_fax_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `client_id` int(11) unsigned NOT NULL,
  `client_phone_1` varchar(45) NOT NULL,
  `client_phone_2` varchar(45) NOT NULL,
  `client_phone_3` varchar(45) NOT NULL,
  `client_fax_1` varchar(45) NOT NULL,
  `client_fax_2` varchar(45) NOT NULL,
  `client_fax_3` varchar(45) NOT NULL,
  PRIMARY KEY (`client_phone_fax_id`) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=33944 DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC;
  • 0
    Можем ли мы предположить, что «% brooklyn%» представляет собой параметр поиска?
  • 1
    Было бы полезно показать типы данных каждого поля и какие поля являются индексами.
Показать ещё 2 комментария
Теги:
optimization

7 ответов

2
Лучший ответ

tb_clients.client_id и tb_clients_phone_fax.client_id должны быть проиндексированы.

Но главной проблемой, по-видимому, являются сравнения двух строк, MATCH и LIKE с CONCAT. Вы уверены, что вокруг нет другой войны? например, избегая конкатенации всех полей адреса перед выполнением инструкции LIKE?

UPDATE: Похоже, что tb_clients_phone_fax.client_id не индексируется, это улучшит производительность, если она будет проиндексирована.

  • 0
    На самом деле он работал довольно быстро, прежде чем я добавил: tb_clients.client_id = tb_clients_phone_fax.client_id Я только что попытался извлечь CONCAT, и он все еще работает довольно медленно ...
  • 0
    tb_clients_phone_fax.client_id не проиндексирован, индексируйте его!
Показать ещё 3 комментария
1

первый шаг при отладке медленных запросов работает EXPLAIN SELECT ... и смотрит на то, что на самом деле делает MySQL, вместо того, чтобы гадать. Но да, похоже, что индекс tb_clients_phone_fax.client_id поможет, как говорили другие.

1

Не зная о вашей ситуации, моя первая мысль, помимо упомянутого указателя, заключается в следующем: сколько строк находится в этих двух таблицах? Один из них - всего несколько тысяч, а другой - десять миллионов? Предполагая, что производительность вашего запроса не связана с соединением с очень большим набором данных, тогда:

Как говорили другие, проверьте, что ваши столбцы проиндексированы. Кроме того, почему не полный текст индексирует столбцы, которые вы конкатенации, а затем используйте второй запрос MATCH() AGAINST() в своем запросе вместо CONCAT() и LIKE?

Как насчет обновления кода для проверки, скажем, шаблона zip-кода, а затем для написания вашего запроса? Или, скажем, если это не шаблон в виде zip-кода, тогда не беспокойтесь о поиске этого столбца.

Одна вещь, которая хорошо работала для меня в ситуациях с большими объемами, где нужно искать всю (большую) таблицу, - это создать столбец, содержащий конкатенацию всей таблицы. Я помещаю полный текст в этот столбец и использую MATCH() AGAINST() и имеет очень быстрое время запроса, поэтому, по моему опыту, полнотекстовое индексирование выполняет свою работу.

Теперь, если у вас очень большая таблица, то объединение в режиме реального времени может стать неприемлемым. На данный момент у вас есть несколько вариантов, но все они - варианты выполнения этого объединения в фоновом режиме и сохранение этого результата в интересах конечных пользователей.

  • 0
    Ну, на самом деле обе таблицы содержат одинаковое количество строк. Что-то вроде 30 КБ ... Целесообразно проверить почтовый индекс, но у нас есть клиенты в разных странах, у которых совершенно разные почтовые индексы: \ - планируем проверить индекс завтра ...
1

Не видя схемы таблицы, трудно сказать наверняка, но я бы предположил, что вы не ищете никаких указаний.

Попробуйте проверить руководство MySQL по полнотекстовым поискам: http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html Для лучшего ответа вам, скорее всего, потребуется опубликовать свою схему и указатели.

1

Вы должны начать, убедившись, что tb_clients имеет индекс для client_id, а tb_clients_phone_fax имеет индекс на client_id.

Затем попробуйте добавить индексы для клиентской компании, описания клиента, ключевых слов клиента.

Однако я готов поспорить, что основное замедление идет на сравнение, которое вы делаете на конкатенированном client_address,client_city,client_state,client_zip, поэтому попробуйте найти другой способ сделать это сравнение без concat. Можете ли вы добавить поле в таблицу, в которой хранятся данные этих элементов, а затем просто сравнить это поле? (Ужасно я знаю)

0

Один очень маленький совет:

CONCAT(client_address,' ',client_city,', ',client_state,' ',client_zip) LIKE '%brooklyn%'

Нужен ли весь CONCAT? У вас много клиентов с brooklyn внутри своего состояния или почтового индекса?

(Также вы понимаете, что это будет соответствовать адресу, например

1342 Бруклин-стрит
Foobar, MI 98765

Это намеренно?)

  • 0
    хороший момент, я даже не думал об этом ...
0

Я бы создал представление для таблицы tb_clients, у которой был "поддельный" столбец, который будет содержать вашу конкатенированную информацию.

Кроме того, я бы индексировал ранее упомянутые столбцы идентификаторов.

тогда вы должны использовать один и тот же базовый запрос, заменив представление для таблицы и опуская concat (поскольку это выполняется представлением как совокупный столбец)

Я в 5 минутах от работы, поэтому я не могу вдаваться в подробности. Если вам нужен код, пример sql и т.д., Дайте мне знать, и я поставлю что-то вместе для вас позже сегодня или завтра.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню