MySQL оператор внутреннего соединения и переполнение памяти! - PullRequest
2 голосов
/ 20 августа 2010

я запускаю приведенный ниже запрос для извлечения из 3 таблиц mysql, и он отлично работает, но увеличивает потребление памяти и иногда для загрузки страницы требуется 10 секунд

  INNER JOIN table_tags AS ntg ON (ns.tags = '' OR CONCAT(' ',COALESCE(ns.tags,' '),' ') LIKE CONCAT('% ',ntg.tid,' %'))
  INNER JOIN table_topics AS nto ON (ns.associated = '' OR CONCAT(' ',COALESCE(ns.associated,'-'),' ') LIKE CONCAT('%',nto.topicid,'%' ))

проблема во внутреннем соединении statemnet, и если я удаляю

ns.tags = '' ИЛИ ​​

и

ns.associated = '' ИЛИ ​​

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

есть ли другой способ написать нижеприведенное заявление, чтобы включить все истории, даже те, которые не имеют тегов!?

  INNER JOIN table_tags AS ntg ON (ns.tags = '' OR CONCAT(' ',COALESCE(ns.tags,' '),' ') LIKE CONCAT('% ',ntg.tid,' %'))

идентификатор моего тега хранится в table_ns, например (14 17 2), разделенных пробелом

1 Ответ

1 голос
/ 21 августа 2010

Ваше условие ns.tags = '' OR ... означает, что, если ns.tags = '' истинно, эта запись из таблицы table_stories будет объединена с всеми записями в table_tags.То же самое с ns.associated = '' OR ...Это может легко «создать» наборы результатов huuuge, и это, скорее всего, не то, что вы хотите.
Если вы действительно не хотите / не можете изменить / нормализовать структуру таблицы (как вы заявили в комментарии к моему предыдущемуответ) мое лучшее предположение - использовать два LEFT JOIN , например:

SELECT
  ns.*,
  ntg.tid,
  nto.topicid,
  group_concat(DISTINCT ntg.tag ) as mytags,
  group_concat(DISTINCT ntg.slug ) as tagslug,
  group_concat(DISTINCT nto.topicname ) as mytopics,
  group_concat(DISTINCT nto.slug ) as topicslug,
  ns.counter AS counter_num
FROM
  table_stories AS ns
LEFT JOIN
  table_tags AS ntg
ON
  CONCAT(' ', ns.tags,' ') LIKE CONCAT('% ',ntg.tid,' %')
LEFT JOIN
  table_topics AS nto
ON
  CONCAT(' ', ns.associated, ' ') LIKE CONCAT('%',nto.topicid,'%' )
WHERE
  time <= '4711'
GROUP BY
  ns.sid
ORDER BY
  ns.sid DESC,ns.hotnews DESC

Но MySQL не может использовать индексы для этого, поэтому запрос приведет к полному сканированию таблицы.Также потребуются временные таблицы и сортировка файлов, то есть запрос будет относительно медленным.
Без изменения структуры таблицы , но формат данных с 1 2 3 на 1,2,3 вы можете по крайней мере избавитьсяConcat() и LIKE с использованием немного более быстрого FIND_IN_SET (str, strlist) .


Только для полноты и на случай, если вы передумаете: http://en.wikipedia.org/wiki/Database_normalization

...