Php 使用SELECT IN MySQL更快地搜索IN语句
我目前正在为我的应用程序执行一些查询,我需要获取当前位置上最近的商店,要执行此操作,首先我需要获取所有具有相同名称的项目,然后获取其信息并缩减该查询。现在我在这个语句中使用了,但由于正在搜索的项目也基于列表,因此我需要使用另一个select。到目前为止,这是我的代码:Php 使用SELECT IN MySQL更快地搜索IN语句,php,mysql,sql,Php,Mysql,Sql,我目前正在为我的应用程序执行一些查询,我需要获取当前位置上最近的商店,要执行此操作,首先我需要获取所有具有相同名称的项目,然后获取其信息并缩减该查询。现在我在这个语句中使用了,但由于正在搜索的项目也基于列表,因此我需要使用另一个select。到目前为止,这是我的代码: select * from product p, store s, branches b where 1 = 1 and b.idproduct = p.idproduct and p.store = s.idstore and
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)
现在它可以按我所希望的那样工作,但我希望它能更快地完成查询。目前,这个查询的运行速度要比这个快3秒多。如果不到一秒钟,效果会更好。我还可以使用其他选项吗?这是您的查询,可以使用正确的
join
语法:
select *
from product p join
store s
on p.store = s.idstore join
branches b
on b.idproduct = p.idproduct
where p.common_name IN (SELECT p.common_name
FROM shopping_list_content slc join
product p
ON slc.iditem = p.idproduct AND
slc.idlist = $listid
);
假设相同的common\u名称
没有出现在多个产品上,并且购物列表内容
没有重复的行,您可以用简单的连接来替换它:
select *
from product p join
store s
on p.store = s.idstore join
branches b
on b.idproduct = p.idproduct join
shopping_list_content slc
on slc.iditem = p.idproduct and
slc.idlist = $listid;
然而,这些假设可能并不正确。在这种情况下,将子查询更改为使用exists
可能有助于提高性能:
select *
from product p join
store s
on p.store = s.idstore join
branches b
on b.idproduct = p.idproduct
where exists (SELECT 1
FROM shopping_list_content slc join
product p2
on slc.iditem = p2.idproduct AND
slc.idlist = $listid
WHERE p.common_name = p2.common_name
);
对于后一个查询,product(common\u name,idproduct)
上的索引以及shopping\u list\u内容(iditem,idlist)
应该会有所帮助。MySQL在优化子查询时遇到困难,例如:
SELECT *
FROM T
WHERE T.ID (SELECT ID FROM T2);
它有时被改写为
SELECT *
FROM T
WHERE EXISTS
( SELECT 1
FROM T2
WHERE T.ID = T2.ID
);
然后在T
中每行执行一次子查询,而如果您写入:
SELECT T.*
FROM T
INNER JOIN
( SELECT DISTINCT ID
FROM T2
) T2
ON T2.ID = T.ID;
您的结果集将是相同的,但是MySQL将首先用子查询的结果填充内存中的表,并将其散列在T2.ID上,然后只需要针对T
中的每一行查找该散列表
您想要的行为实际上取决于您希望从每个表/子查询中获得多少数据。如果在T2
中有100万行,在T
中有10行,那么用100万行填充一个临时表是没有意义的,只是随后只使用它10次,然而,如果在T
中有大量行,而在T2
中只有少量行,那么从长远来看,实现子查询的额外成本将是有益的
需要指出的另一点是(这对性能没有影响),您使用的连接语法是ANSI 89语法,20多年前被ANSI 92显式连接语法取代。虽然针对SQL Server,但我认为可以很好地总结切换到较新联接语法的原因。进行最终查询:
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;
注意:如果您使用的是MySQL 5.6.5或更高版本,以上大部分内容不适用。在这个版本中,他们引入了更多解决上述许多问题的方法对您的查询做一个解释,检查索引,并寻找用JOIN1=1替换In,将给出所有行为什么在每个查询/子查询中使用1=1
子句?如果你让其他人知道WHERE子句我错了,那就没有意义了?请尝试更改为存在,如和common\u name IN(选择p.common\u name
到和common\u name EXIST(选择1…
我现在将尝试加入。)这真的很好!我的意思是解释MySQL是如何处理它的。哇!这是一个非常快速的解决方案。完成查询只需要0.0480秒。非常感谢!:D