MySql Query - 使用 varchars、索引进行优化,需要一个多小时才能运行
Posted
技术标签:
【中文标题】MySql Query - 使用 varchars、索引进行优化,需要一个多小时才能运行【英文标题】:MySql Query - optimization with varchars, indexs, taking over an hour to run 【发布时间】:2016-05-07 16:55:06 【问题描述】:所以我需要运行一个我不知道 UUID 的查询 - 但需要找到它...所以我使用街道编号、街道名称和公司 UUID 来查找它
我有几百万条记录,这个耗时查询大约需要一个小时!!
有什么建议可以加快速度吗?
gisPoints
UUID Indexed Unique varchar(36)
street_num int(11)
street_name varchar(128)
geoPoint_temp
UUID Indexed Unique varchar(36)
street_num int(11)
street_name varchar(128)
gcomUUID Indexed varchar(36)
update geoPoint_temp as temp JOIN gisPoints as `prod` on prod.gcomUUID=temp.gcomUUIDand prod.street_num=temp.street_num and prod.street_name REGEXP(temp.street_name)
set temp.UUID=prod.UUID,temp.customerUUID=prod.customerUUID WHERE temp.`uploadstate` = '1'";
【问题讨论】:
您的查询中发生了什么?我看到您正在执行更新,但是在什么表上?您是否正在执行 JOIN 操作以创建“临时表”,然后更新该临时表?还是您想更新已经存在的表? 我将 gisPoints 中的 UUID 插入到 geoPoint_temp 表中 我知道,但是当您执行JOIN
操作时,您正在创建一个临时表。因此,如果我有例如SELECT a.ID, b.DATE FROM a JOIN b ON a.ID = b.ID
,我将创建一个既不是a
也不是b
的表。因此,您的代码当前正在执行UPDATE (your join code) SET ...
,您的连接代码正在创建一个临时表。你同意我更新的表是临时的吗?
好吧...有道理,我正在更新 geoPoint_temp,而不是临时表
您的表格是否正在更新?过了一小时后更新了吗?
【参考方案1】:
假设您有以下值(在 php 中):
$street_num = ...;//something
$street_name = ...;//something
$gcomUUID = ...;//something
如果你运行下面的sql代码:
$sql = "SELECT * FROM (
SELECT * FROM (
SELECT * FROM geoPoint_temp WHERE gcomUUID = $gcomUUID)
WHERE street_name = $street_name)
WHERE street_num = $street_num;"
您应该从 geoPoint_temp 中获取具有匹配值的行列表(0 或更多),并且即使在大表中也应该相对较快。
获取这些行后,您可以检查行数是否大于零,如果是,则更新行。如果您使用 mysql (PDO),您可以执行类似以下操作:
$count = $stmt->rowCount();
if ($count>0)
$rows = $stmt->fetchAll();
foreach ($rows as $row)
$sql = "UPDATE geoPoint_temp SET ... WHERE UUID = ".$row['UUID'];
$stmt = $conn->prepare($sql);
$stmt->execute();
如果有帮助,请告诉我。
已编辑:
尝试以下方法,如果有效,请告诉我:
$sql = "
UPDATE geoPoint_temp SET ... WHERE UUID IN
(SELECT * FROM (
SELECT * FROM (
SELECT * FROM geoPoint_temp WHERE gcomUUID = $gcomUUID)
WHERE street_name = $street_name)
WHERE street_num = $street_num);"
并将...
替换为您要更新的值。
【讨论】:
我必须有一个额外的查询,然后做一个while循环遍历geoPoint_temp来填写street_num、street_name、gcomUUID。我想做的是让mysql做繁重的工作 我很确定 sql 可以完成所有这些,但我个人不确定如何为UPDATE
查询编写条件。如果我将答案中的第一个 $sql
语句修改为以 $sql = "SELECT ID FROM ...
开头并保持所有其余部分相同,我实际上会有一列需要更新的 ID,但是在更新时,我不知道的是如何使用列编写 where 条件:UPDATE geoPoint_temp SET ... WHERE ???
。我知道我们已经有一个需要比较 ID 的列,但是 sql 是否允许您比较 WHERE UUID = [column obtained]
?
@morty346 很酷,如果可行,请告诉我你是如何做到的,我也有兴趣知道哈哈
@morty346 我已经用一个应该可以使用的选项更新了我的答案,如果可以,请告诉我。
在下面添加了我的 - 如果你想更新你的以反映变化,我很乐意选择你的作为答案 - 因为你让我们朝着正确的方向前进 - 再次感谢!【参考方案2】:
这运行时间为 1.5 秒,而之前需要几个小时 @Webeng 为我们指明正确的方向提供了很大帮助!
$custquery="UPDATE geoPoint_temp as temp
join
(
select prod.name, prod.street_num, prod.street_name, prod.UUID,prod.customerUUID, prod.gcomUUID
FROM gisPoints as `prod`
JOIN
(
select t1.gcomUUID , t1.street_num, t1.street_name
FROM geoPoint_temp as t1
) as sub1 on prod.gcomUUID =sub1.gcomUUID and prod.street_num=sub1.street_num
) as sub2 on sub2.gcomUUID =temp.gcomUUID
and sub2.street_num=temp.street_num
AND sub2.street_name LIKE (CONCAT('%',temp.street_name,'%'))
set temp.customerUUID = sub2.customerUUID, temp.UUID=sub2.UUID";
$custre=mysql_query($custquery);
if (!$custre) echo 'Could not run custre query: ' . mysql_error(); exit;
【讨论】:
以上是关于MySql Query - 使用 varchars、索引进行优化,需要一个多小时才能运行的主要内容,如果未能解决你的问题,请参考以下文章