2

这需要很长时间才能完成,但希望能够快速提取它收集的信息。

SELECT *
FROM releases
WHERE (artist IN (SELECT artist FROM artist_love WHERE user='Quickinho')
OR
label IN (SELECT label FROM label_love WHERE user='Quickinho')
OR
id IN (SELECT release_id FROM charts_extended WHERE artist IN (SELECT dj FROM dj_love WHERE user='Quickinho'))
OR
id IN (SELECT artist FROM releases WHERE id IN (SELECT release_id FROM charts_extended WHERE user='Quickinho'))
OR
id IN (SELECT label FROM releases WHERE id IN (SELECT release_id FROM charts_extended WHERE user='Quickinho')))
AND
id NOT IN (SELECT release_id FROM charts_extended WHERE user='Quickinho')
ORDER BY date DESC
LIMIT 0,102
4

8 回答 8

8

避免任何子选择(虽然没有测试,所以请原谅任何错别字)

SELECT *
FROM releases
LEFT OUTER JOIN artist_love ON releases.artist = artist_love.artist AND artist_love.user = 'Quickinho'
LEFT OUTER JOIN label_love ON releases.label = label_love.label AND label_love.user = 'Quickinho'
LEFT OUTER JOIN charts_extended ON releases.id = charts_extended.release_id
LEFT OUTER JOIN dj_love ON charts_extended.artist = dj_love.dj AND dj_love.user = 'Quickinho'
LEFT OUTER JOIN releases releases1 ON releases.id = releases1.artist
LEFT OUTER JOIN charts_extended charts_extended1 ON charts_extended1.artist = releases1.id AND charts_extended1.user = 'Quickinho'
LEFT OUTER JOIN releases releases2 ON releases.id = releases2.label
LEFT OUTER JOIN charts_extended charts_extended2 ON charts_extended2.artist = releases2.id AND charts_extended2.user = 'Quickinho'
LEFT OUTER JOIN charts_extended charts_extended3 ON charts_extended3.release_id = releases.id AND charts_extended3.user = 'Quickinho'
WHERE (artist_love.user IS NOT NULL
OR label_love.user IS NOT NULL
OR dj_love.user IS NOT NULL
OR charts_extended1.user IS NOT NULL
OR charts_extended2.user IS NOT NULL)
AND charts_extended3.user IS NULL
于 2012-10-13T20:10:36.353 回答
4

其他人提供的优化查询可能还不够快。

假设您的原始查询需要 120 秒才能执行,而最佳优化查询仍然需要 30 秒,但您需要 5 秒或更好的响应时间。你能做什么?

预填充!

运行由定期执行的cron 作业触发的查询,例如每小时一次。使用这样的INSERT SELECT查询:

INSERT INTO releases_queried
SELECT -- your query (your original one or one of the optimized ones)

请参阅MySQL 手册 INSERT-SELECT。然后你会得到结果

SELECT * FROM releases_queried

立即在几毫秒内。这是一种众所周知的改进响应时间的技术。如果查询所需的数据始终可用,则效果很好。

现实世界的使用

StackOverflow 本身有许多复杂的查询不是按请求完成的,而是异步完成的。徽章不是在每次访问时计算的,而是按 cron 计算的。

于 2012-10-13T20:31:07.627 回答
3
...from releases
WHERE (artist IN (SELECT artist FROM artist_love WHERE user='Quickinho')

我建议你使用JOIN而不是做IN (SELECT..)

你可以做类似的事情

select r.* from releases r, artist_love al 
where r.artist = al.artist and al.user='Quickinho'
于 2012-10-08T10:37:41.787 回答
2

IN() 和 NOT IN() 子查询优化不佳
MySQL 将子查询作为外部查询中每一行的依赖子查询执行。这是 MySQL 5.5 和更早版本中严重性能问题的常见原因。查询可能应该分别重写为 JOIN 或 LEFT OUTER JOIN。

选择 *

如果表的架构发生变化,选择所有带有 * 通配符的列将导致查询的含义和行为发生变化,并可能导致查询检索到过多的数据。

于 2012-10-11T07:04:18.013 回答
1

首先 - 使 JOIN 关系中使用的所有字段都被索引。

然后试试这个查询 -

SELECT
  r.*
FROM
  releases r
LEFT JOIN (SELECT artist FROM artist_love WHERE user='Quickinho') al
  ON al.artist = r.artist
LEFT JOIN (SELECT label FROM label_love WHERE user='Quickinho') ll
  ON ll.label = r.label
LEFT JOIN (
    SELECT release_id FROM charts_extended ce
    INNER JOIN (SELECT dj FROM dj_love WHERE user='Quickinho') djl
      ON djl.dj = ce.artist
    ) ce
  ON r.id = ce.release_id
LEFT JOIN (
    SELECT artist FROM releases r
    INNER JOIN (SELECT release_id FROM charts_extended WHERE user='Quickinho') ce
      ON r.id = release_id
  ) r2
  ON r2.artist = r.id OR r2.label = r.id

LEFT JOIN (SELECT release_id FROM charts_extended WHERE user='Quickinho') ce2
  ON ce2.release_id = r.id

WHERE
  (al.artist IS NOT NULL OR ll.label IS NOT NULL OR ce.release_id IS NOT NULL OR r2.id IS NOT NULL)
  AND ce2.release_id IS NULL
GROUP BY
  r.id
于 2012-10-12T06:39:08.500 回答
1

Kickstart 的解决方案是正确的想法(尽管我建议您尽可能在 USER 上加入,但让“user = 'Quickinho'”出现这么多次并不是一个好习惯),然后考虑为以下部分或全部字段添加索引:

  • 艺术家爱艺术家
  • label_love.label
  • chart_extended.release_id
  • dj_love.dj
  • 发布.艺术家
  • 发布.标签
  • chart_extended.release_id

虽然我不能说我能想到你想用这个做什么。可能有更好的解决方案。

于 2012-10-16T07:01:24.013 回答
1

您可以搜索key_cache, SQL Partition, performance tuning;

于 2012-10-16T09:40:38.953 回答
1

您可以使用JOIN来提高性能。在 JOIN 中,RDBMS 可以创建一个更适合您的查询的执行计划,这与子查询不同,子查询将运行所有查询并加载所有数据以进行处理。

于 2012-10-17T17:24:50.453 回答