mysql选择内部连接的顺序非常慢

发布于 2025-01-23 15:41:50 字数 686 浏览 3 评论 0原文

我正在尝试加快MySQL查询。列表表有数百万行。如果我以后不整理它们,我会在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;

解释选择:使用索引l =日期,loc = primary,lc = primary

I'm trying to speed up a mysql query. The Listings table has several million rows. If I don't sort them later I get the result in 0.1 seconds but once I sort it takes 7 seconds. What can I improve to speed up the query?

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: Using Index l=date, loc=primary, lc=primary

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

夜还是长夜 2025-01-30 15:41:50

这样的绩效问题确实很难回答,并且取决于设置,索引等。因此,可能不会唯一的解决方案,甚至没有真正正确或不正确的尝试来提高速度。这是尝试和错误的洛夫。无论如何,我注意到的某些观点经常引起性能问题:

  • 避免在加入中应放置在哪里。连接应包含仅将要加入的列,没有进一步的条件。因此,应将“ LC.CAT_ID ='2058”放在Where子句中。
  • 使用通常很慢。您可以尝试使用或使用(l.location_id = 7841或location_id = 7842或...)
  • 打开查询执行计划并检查是否对您有用。
  • 尝试找出受影响的列中是否有特殊情况/值,这些列中的查询更改为
  • “按日期”更改为“ by tablealias.s.date”,并检查这是否会有所作为。即使没有,也最好阅读。
  • 如果您可以重命名“日期”列,请执行此操作,因为将SQL关键字用作表名称或列名是不是一个好主意。我不确定这是否会影响性能,但是如果可能的话,应该避免这种情况。

祝你好运!

Such performance questions are really difficult to answer and depend on the setup, indexes etc. So, there will likely not the one and only solution and even not really correct or incorrect attempts to improve the speed. This is a lof of try and error. Anyway, some points I noted which often cause performance issues are:

  • Avoid conditions within joins that should be placed in the where instead. A join should contain the columns only that will be joined, no further conditions. So the "lc.cat_id='2058" should be put in the where clause.
  • Using IN is often slow. You could try to replace it by using OR (l.location_id = 7841 OR location_id = 7842 OR...)
  • Open the query execution plan and check whether there is something useful for you.
  • Try to find out if there are special cases/values within the affected columns which slow down your query
  • Change "ORDER BY date" to "ORDER BY tablealias.date" and check if this makes a difference in performance. Even if not, it is better to read.
  • If you can rename the column "date", do this because using SQL keywords as table name or column name is no good idea. I'm unsure if this influences the performance, but it should be avoided if possible.

Good luck!

无戏配角 2025-01-30 15:41:50

您可以尝试使用附加索引来加快查询的速度,但是在创建/操纵数据时,您将有一个权衡。

这些组合的密钥可以加快查询:

listings: date, location_id 
listings_categories: cat_id, list_id

由于计划说它使用日期索引,因此无需读取记录以在USIGN新索引时检查location_id,而与listInngs_category一起使用,请阅读index足够了

You can try additonal indexes to speed up the query, but you'll have a tradeoff when creating/manipulating data.

These combined keys could speed up the query:

listings: date, location_id 
listings_categories: cat_id, list_id

Since the plan says it uses the date index, there wouldn't be a need to read the record to check the location_id when usign the new index, and same for the join with listinngs_category, index read would be enough

作业与我同在 2025-01-30 15:41:50
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)

这个想法,请在到达桌子本身之前从索引中获取10个ID。在排序之前,您的版本可能会在整个桌子上铲除,然后交付10。

l:  INDEX(location_id, id)
lc:  INDEX(cat_id, list_id)

If those don't suffice, try the following rewrite.

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 

With

listings:  INDEX(location_id, date, id)
listings_categories:  INDEX(cat_id, list_id)

The idea here is to get the 10 ids from the index before reaching to the table itself. Your version is probably shoveling around the whole table before sorting, and then delivering the 10.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文