donglu2523 2014-03-03 14:14 采纳率: 100%
浏览 152
已采纳

使用MySQL中的SELECT更快地搜索IN语句

I'm currently doing some query for my app and I need to get the nearest store on my current position and to do this first I need to get all the item that has the same name then get it's information and trim down that query. Now I used IN statement for this but since the items being searched are also based on a list I need to make use of another select for this here is my code so far:

select *
from product p,
store s,
branches b
where 1 = 1
and b.idproduct = p.idproduct
and p.store = s.idstore
and common_name IN(SELECT p.common_name
FROM shopping_list_content s, product p
WHERE 1 =1
AND s.iditem = p.idproduct
AND s.idlist =$listid)

Now it works as I wanted it to be but I wanted it to do the query faster than this. For now it takes more than 3 seconds for this query to run faster than this. much better if it is less than a second. Any other option I can use for this?

  • 写回答

2条回答 默认 最新

  • duanhuan2301 2014-03-03 14:38
    关注

    MySQL has difficulty optimising subqueries, when you write something like:

    SELECT  *
    FROM    T
    WHERE   T.ID (SELECT ID FROM T2);
    

    It is sometimes rewritten as

    SELECT  *
    FROM    T
    WHERE   EXISTS
            (   SELECT  1
                FROM    T2
                WHERE   T.ID = T2.ID
            );
    

    The subquery is then executed once per row in T, whereas if you write:

    SELECT  T.*
    FROM    T
            INNER JOIN
            (   SELECT  DISTINCT ID
                FROM    T2
            ) T2
                ON T2.ID = T.ID;
    

    Your result set will be the same, but MySQL will first fill an in memory table with the results of the subquery and hash it on T2.ID, it then just needs to lookup against this hash table for each row in T.

    Which behaviour you want really depends on how much data you are expecting from each table/subquery. If you have 1 million rows in T2, and 10 in T then there is no point in filling a temporary table with 1 million rows, only to subsequently only use it 10 times, whereas if you have a large number of rows in T and only a small amount in T2 the additional cost of materialising the subquery will be beneficial in the long run.

    Another thing to point out (which has no impact on performance), the JOIN syntax you are using is the ANSI 89 syntax and was replaced by ANSI 92 explicit JOIN syntax over 20 years ago. Although directed at SQL Server, I think this article summarises the reasons to switch to the newer join syntax very well. Making your final query:

    SELECT  *
    FROM    product p,
            INNER JOIN store s
                ON p.store = s.idstore
            INNER JOIN branches b
                ON b.idproduct = p.idproduct
            INNER JOIN
            (   SELECT DISTINCT p.common_name
                FROM    shopping_list_content s
                        INNER JOIN product p
                            ON s.iditem = p.idproduct
                WHERE   s.idlist =$listid
            ) s
                ON s.common_name = p.common_name;
    

    N.B. Most of the above does not apply if you are using MySQL 5.6.5 or later. In this version they introduced more Subquery Optimization that solved a lot of the above issues

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥30 自适应 LMS 算法实现 FIR 最佳维纳滤波器matlab方案
  • ¥15 lingo18勾选global solver求解使用的算法
  • ¥15 全部备份安卓app数据包括密码,可以复制到另一手机上运行
  • ¥15 Python3.5 相关代码写作
  • ¥20 测距传感器数据手册i2c
  • ¥15 RPA正常跑,cmd输入cookies跑不出来
  • ¥15 求帮我调试一下freefem代码
  • ¥15 matlab代码解决,怎么运行
  • ¥15 R语言Rstudio突然无法启动
  • ¥15 关于#matlab#的问题:提取2个图像的变量作为另外一个图像像元的移动量,计算新的位置创建新的图像并提取第二个图像的变量到新的图像