MySQL中的长UPDATE查询

时间:2012-03-30 14:22:02

标签: php mysql

我必须运行一些mysql更新查询,它们需要很长时间才能运行。我使用PHP脚本,但每次更新需要40到600毫秒,通常大约250毫秒。

我尝试尽可能地优化,但脚本运行时间仍然超过30分钟(两个表中的20000个条目)。

这是我的PHP脚本和UPDATE查询的一部分:

if (mysql_num_rows($Rmaster) == 1) {
//Start time
    $Qchange_name = 'UPDATE slave SET NewAreaName = "'.$Amaster['AreaName'].'" WHERE Dialcode = "'.$Amain['Dialcode'].'" ORDER BY Dialcode ASC LIMIT 1 ';
    $Rchange_name = mysql_query($Qchange_name, $link);
//end time = 40 to 600ms
}

我的SELECT查询速度很快,我在两个表中都有一个Dialcode指数

这些是我的表格(简化):

CREATE TABLE IF NOT EXISTS `master` (
  `Dialcode` varchar(11) DEFAULT NULL,
  `AreaName` varchar(45) DEFAULT NULL,
  KEY `Dialcode` (`Dialcode`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Table structure for table `slave`
--
CREATE TABLE IF NOT EXISTS `slave` (
  `AreaName` varchar(47) DEFAULT NULL,
  `NewAreaName` varchar(47) NOT NULL,
  `Dialcode` varchar(15) DEFAULT NULL,
  KEY `Dialcode` (`Dialcode`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

还有什么我可以尝试让它更快?

PHP:5.3.4

MySQL:5.1.53

(本周末我将首先尝试PDO解决方案并更新帖子)谢谢!

更新: 我尝试了PDO这两个不同的查询:

$Qchange_name = $pdo->prepare('UPDATE slave SET NewAreaName = ? WHERE DIalcode = ?');
$Qchange_name = $pdo->prepare('REPLACE INTO slave SET NewAreaName = ? AND Dialcode = ?');

但只需要花费大约18秒的时间来完成150行的foreach!

在我的主循环中,我做了:

$L4 = array(); // Before the loops
else if ($countQmaster1 == 1) {
   $L4[] = array($Amaster1['AreaName'], $Amain['Dialcode']);        
}

然后在循环结束时:

foreach ($L4 as $b){
    $Qchange_name->execute($b); 
}

此外,我还将Dialcode作为PRIMARY INDEX

我做错了吗?

更新:隔离查询。

以下是创建表格和代码的文件。我隔离了查询并减少了脚本,但仍然需要17秒才能运行150行。

你知道有什么不对吗?你得到相同的结果吗?

PHP代码here 要么 here

要下载herehere

我在考虑缓冲问题?我正在我的本地计算机上运行,​​并且我得到了一些快速和缓慢的更新。

1 was executed in 38.87 ms 
2 was executed in 33.05 ms 
3 was executed in 33.17 ms 
4 was executed in 91.42 ms 
5 was executed in 36.17 ms 
6 was executed in 30.23 ms 
7 was executed in 33.15 ms 
8 was executed in 33.21 ms 
9 was executed in 33.22 ms 
10 was executed in 42.72 ms 
11 was executed in 32.12 ms 
12 was executed in 33.04 ms 
13 was executed in 33.14 ms 
14 was executed in 33.2 ms 
15 was executed in 33.2 ms 
16 was executed in 33.16 ms 
17 was executed in 33.25 ms 
18 was executed in 33.2 ms 
19 was executed in 33.12 ms 
20 was executed in 33.25 ms 
21 was executed in 33.15 ms 
22 was executed in 33.21 ms 
23 was executed in 33.16 ms 
24 was executed in 41.54 ms 
25 was executed in 74.79 ms 
26 was executed in 129.35 ms 
27 was executed in 77.65 ms 
28 was executed in 34.06 ms 
29 was executed in 33.21 ms 
30 was executed in 33.2 ms 
31 was executed in 33.17 ms 
32 was executed in 140.5 ms 
33 was executed in 34.04 ms 
34 was executed in 41.53 ms 
35 was executed in 33.23 ms 
36 was executed in 33.14 ms 
37 was executed in 158.06 ms 
38 was executed in 149.8 ms 
39 was executed in 278.14 ms 
40 was executed in 154.52 ms 
41 was executed in 149.71 ms 
42 was executed in 91.45 ms 
43 was executed in 274.55 ms 
44 was executed in 149.77 ms 
45 was executed in 278.46 ms 
46 was executed in 1055.73 ms 
47 was executed in 280.42 ms 
48 was executed in 149.85 ms 
49 was executed in 154.48 ms 
50 was executed in 178.14 ms 
51 was executed in 158.06 ms 
52 was executed in 433.23 ms 
53 was executed in 149.22 ms  
54 was executed in 166.41 ms 
55 was executed in 41.5 ms 
56 was executed in 33.21 ms 
57 was executed in 41.52 ms 
58 was executed in 33.16 ms 
59 was executed in 33.19 ms 
60 was executed in 49.8 ms 
61 was executed in 33.21 ms 
62 was executed in 33.16 ms 
63 was executed in 41.55 ms 
64 was executed in 33.13 ms 
65 was executed in 58.25 ms 
66 was executed in 33.12 ms 
67 was executed in 41.52 ms 
68 was executed in 33.15 ms 
69 was executed in 33.21 ms 
70 was executed in 41.51 ms 
71 was executed in 33.18 ms 
72 was executed in 33.19 ms 
73 was executed in 41.52 ms 
74 was executed in 33.25 ms 
75 was executed in 33.15 ms 
76 was executed in 41.58 ms 
77 was executed in 33.1 ms 
78 was executed in 33.17 ms 
79 was executed in 41.53 ms 
80 was executed in 33.18 ms 
81 was executed in 41.49 ms 
82 was executed in 33.15 ms 
83 was executed in 33.22 ms 
84 was executed in 41.52 ms 
85 was executed in 33.19 ms 
86 was executed in 33.19 ms 
87 was executed in 66.5 ms 
88 was executed in 33.16 ms 
89 was executed in 75.42 ms 
90 was executed in 57.55 ms 
91 was executed in 33.27 ms 
92 was executed in 41.43 ms 
93 was executed in 33.14 ms 
94 was executed in 33.19 ms 
95 was executed in 41.54 ms 
96 was executed in 33.15 ms 
97 was executed in 33.24 ms 
98 was executed in 41.45 ms 
99 was executed in 33.23 ms 
100 was executed in 33.15 ms 
101 was executed in 41.55 ms 
102 was executed in 33.22 ms 
103 was executed in 274.54 ms 
104 was executed in 291.28 ms 
105 was executed in 149.72 ms 
106 was executed in 91.42 ms 
107 was executed in 274.68 ms 
108 was executed in 278.38 ms 
109 was executed in 154.23 ms 
110 was executed in 432.75 ms 
111 was executed in 424.47 ms 
112 was executed in 309.66 ms 
113 was executed in 1101.32 ms 
114 was executed in 327.63 ms 
115 was executed in 116.23 ms 
116 was executed in 34.24 ms 
117 was executed in 33.18 ms 
118 was executed in 65.39 ms 
119 was executed in 34.36 ms 
120 was executed in 30.48 ms 
121 was executed in 35.85 ms 
122 was executed in 33.18 ms 
123 was executed in 41.54 ms 
124 was executed in 33.13 ms 
125 was executed in 33.23 ms 
126 was executed in 41.49 ms 
127 was executed in 83.13 ms 
128 was executed in 33.13 ms 
129 was executed in 41.58 ms 
130 was executed in 33.15 ms 
131 was executed in 33.17 ms 
132 was executed in 41.5 ms 
133 was executed in 33.18 ms 
134 was executed in 41.54 ms 
135 was executed in 33.13 ms 
136 was executed in 33.19 ms 
137 was executed in 41.55 ms 
138 was executed in 33.14 ms 
139 was executed in 33.21 ms 
140 was executed in 41.5 ms 
141 was executed in 33.22 ms 
142 was executed in 33.17 ms 
143 was executed in 41.51 ms 
144 was executed in 33.13 ms 
145 was executed in 33.22 ms 
146 was executed in 41.51 ms 
147 was executed in 75.34 ms 
148 was executed in 39.76 ms 
149 was executed in 34.38 ms  
150 was executed in 33.12 ms 

This script was executed in 13.45 seconds

这是配置:

# The MySQL server
[wampmysqld]
port        = 3306
socket      = /tmp/mysql.sock
query_cache_size=32M
# key_buffer = 16M
max_allowed_packet = 1M
table_cache = 64
sort_buffer_size = 512K
net_buffer_length = 8K
read_buffer_size = 256K
read_rnd_buffer_size = 512K
myisam_sort_buffer_size = 8M

编辑:解决方案

最后,在将ENGINE = InnoDB更改为MyISAM后,查询在不到3秒的时间内执行了20000行!

感谢@JOHN的帮助! PDO帮了很多忙!

4 个答案:

答案 0 :(得分:1)

使用prepared statements(例如mysqliPDO实施)始终尽可能,它们更有效率,可以节省您的sql注入等等。另外,考虑使用mysqli扩展名,mysql被视为过时。

还有一件事需要考虑:如何获得$AmasterAmain值?它们是存储在脚本中还是单独检索每一行?

更详细:

每次使用mysql_query执行查询时,数据库都会执行请求计划。对于影响少量行的查询,与执行本身相比,规划可能需要花费很多时间(此处没有任何统计信息,但我相信在复杂查询和短输出的情况下,它可能是时间的大小)。因此,如果要执行大量类似的查询 - 由于为每个查询执行计划,因此效率非常低。

为避免这种情况,您应该使用预准备语句。这背后的想法是创建一个命名对象,可以缓存查询计划并跳过计划过程,直接跳到执行步骤。

在实践中,我遇到一种情况,使用预处理语句与原始SQL查询(约100000条记录)相比,执行速度提高了约100倍

在DBMS中应该支持准备好的语句,但据我所知,它们是supported in Mysql 5.0

一些样本

$pdo = new PDO(/*your database connection properties here*/);
$update_stmt = $pdo->prepare("UPDATE slave SET NewAreaName = ? WHERE Dialcode = ? ORDER BY Dialcode ASC LIMIT 1");

/*Iterate over $Rmaster  as you do it now{*/
    $update_stmt->execute(array($Amaster['AreaName'], $Amain['AreaCode']));
/*}*/

答案 1 :(得分:0)

您的问题可能是因为向您的数据库发出> 20000 + 1个查询。

如果可能,请尝试概括更新语句,以便一次覆盖多行。因此,您可以减少查询的总数。

答案 2 :(得分:0)

答案 3 :(得分:0)

首先,您应该在每个表中使用主键。

如果您将master.DialCode更改为非空主键,它将会有很多帮助。

slave.DialCode也是唯一的吗?如果没有,为什么你会在查询中排序并限制?

当你有主键时,你可以尝试捆绑更多的记录(比如100或者其他),并一次更新它们。

REPLACE INTO slave (DialCode, NewAreaName) Values
('code1','name1'),
('code2','name2'),
('code3','name3');