Mysql Select INNER JOIN with order by very slow
Mysql Select INNER JOIN with order by very slow
我正在尝试加快 mysql 查询。列表 table 有几百万行。如果我稍后不对它们进行排序,我会在 0.1 秒内得到结果,但一旦我排序它需要 7 秒。我可以改进什么来加快查询速度?
SELECT l.*
FROM listings l
INNER JOIN listings_categories lc
ON l.id=lc.list_id
AND lc.cat_id='2058'
INNER JOIN locations loc
ON l.location_id=loc.id
WHERE l.location_id
IN (7841,7842,7843,7844,7845,7846,7847,7848,7849,7850,7851,7852,7853,7854,7855,7856,7857,7858,7859,7860,7861,7862,7863,7864,7865,7866,7867,7868,7869,7870,7871,7872,7873,7874,7875,7876,7877,7878,7879,7880,7881,7882,7883,7884,7885,7886,7887,7888,7889,7890,7891,7892,7893,7894,7895,7896,7897,7898,7899,7900,7901,7902,7903)
ORDER BY date
DESC LIMIT 0,10;
EXPLAIN SELECT: 使用索引 l=date, loc=primary, lc=primary
这样的性能问题真的很难回答,取决于设置、索引等。因此,可能没有唯一的解决方案,甚至没有真正正确或不正确的提高速度的尝试。这是大量的尝试和错误。无论如何,我注意到一些经常导致性能问题的点是:
- 避免连接中应该放在 where 中的条件。连接应该只包含将要连接的列,没有其他条件。所以“lc.cat_id='2058”应该放在where子句中。
- 使用 IN 通常很慢。您可以尝试使用 OR (l.location_id = 7841 OR location_id = 7842 OR...)
来替换它
- 打开查询执行计划,查看是否有对您有用的东西。
- 尝试查明受影响的列中是否有特殊的 cases/values 会减慢您的查询速度
- 将“ORDER BY date”更改为“ORDER BY tablealias.date”并检查这是否会影响性能。就算不会,也比读书好
- 如果您可以重命名列“日期”,请执行此操作,因为使用 SQL 关键字作为 table 名称或列名称并不是一个好主意。我不确定这是否会影响性能,但应尽可能避免。
祝你好运!
您可以尝试使用附加索引来加快查询速度,但是当 creating/manipulating 数据时,您需要权衡。
这些组合键可以加快查询速度:
listings: date, location_id
listings_categories: cat_id, list_id
因为计划说它使用日期索引,所以在使用新索引时不需要读取记录来检查 location_id,与 [=19= 的连接也是如此], 索引读就够了
l: INDEX(location_id, id)
lc: INDEX(cat_id, list_id)
如果这些还不够,请尝试以下重写。
SELECT l2.*
FROM
(
SELECT l1.id
FROM listings AS l1
JOIN listings_categories AS lc ON lc.list_id = l1.id
JOIN locations AS loc ON loc.id = l1.location_id
WHERE lc.cat_id='2058'
AND l1.location_id IN (7841, ..., 7903)
ORDER BY l1.date DESC
LIMIT 0,10
) AS x
JOIN listings l2 ON l1.id = x.id
ORDER BY l2.date DESC
有
listings: INDEX(location_id, date, id)
listings_categories: INDEX(cat_id, list_id)
这里的想法是在到达 table 本身之前从索引中获取 10 个 id。您的版本可能在排序之前将整个 table 铲掉,然后交付 10.
我正在尝试加快 mysql 查询。列表 table 有几百万行。如果我稍后不对它们进行排序,我会在 0.1 秒内得到结果,但一旦我排序它需要 7 秒。我可以改进什么来加快查询速度?
SELECT l.*
FROM listings l
INNER JOIN listings_categories lc
ON l.id=lc.list_id
AND lc.cat_id='2058'
INNER JOIN locations loc
ON l.location_id=loc.id
WHERE l.location_id
IN (7841,7842,7843,7844,7845,7846,7847,7848,7849,7850,7851,7852,7853,7854,7855,7856,7857,7858,7859,7860,7861,7862,7863,7864,7865,7866,7867,7868,7869,7870,7871,7872,7873,7874,7875,7876,7877,7878,7879,7880,7881,7882,7883,7884,7885,7886,7887,7888,7889,7890,7891,7892,7893,7894,7895,7896,7897,7898,7899,7900,7901,7902,7903)
ORDER BY date
DESC LIMIT 0,10;
EXPLAIN SELECT: 使用索引 l=date, loc=primary, lc=primary
这样的性能问题真的很难回答,取决于设置、索引等。因此,可能没有唯一的解决方案,甚至没有真正正确或不正确的提高速度的尝试。这是大量的尝试和错误。无论如何,我注意到一些经常导致性能问题的点是:
- 避免连接中应该放在 where 中的条件。连接应该只包含将要连接的列,没有其他条件。所以“lc.cat_id='2058”应该放在where子句中。
- 使用 IN 通常很慢。您可以尝试使用 OR (l.location_id = 7841 OR location_id = 7842 OR...) 来替换它
- 打开查询执行计划,查看是否有对您有用的东西。
- 尝试查明受影响的列中是否有特殊的 cases/values 会减慢您的查询速度
- 将“ORDER BY date”更改为“ORDER BY tablealias.date”并检查这是否会影响性能。就算不会,也比读书好
- 如果您可以重命名列“日期”,请执行此操作,因为使用 SQL 关键字作为 table 名称或列名称并不是一个好主意。我不确定这是否会影响性能,但应尽可能避免。
祝你好运!
您可以尝试使用附加索引来加快查询速度,但是当 creating/manipulating 数据时,您需要权衡。
这些组合键可以加快查询速度:
listings: date, location_id
listings_categories: cat_id, list_id
因为计划说它使用日期索引,所以在使用新索引时不需要读取记录来检查 location_id,与 [=19= 的连接也是如此], 索引读就够了
l: INDEX(location_id, id)
lc: INDEX(cat_id, list_id)
如果这些还不够,请尝试以下重写。
SELECT l2.*
FROM
(
SELECT l1.id
FROM listings AS l1
JOIN listings_categories AS lc ON lc.list_id = l1.id
JOIN locations AS loc ON loc.id = l1.location_id
WHERE lc.cat_id='2058'
AND l1.location_id IN (7841, ..., 7903)
ORDER BY l1.date DESC
LIMIT 0,10
) AS x
JOIN listings l2 ON l1.id = x.id
ORDER BY l2.date DESC
有
listings: INDEX(location_id, date, id)
listings_categories: INDEX(cat_id, list_id)
这里的想法是在到达 table 本身之前从索引中获取 10 个 id。您的版本可能在排序之前将整个 table 铲掉,然后交付 10.