查询执行时间问题
Query execution time issue
我对脚本的执行时间有一些疑问。查询需要很多时间。这是查询:
select avg(price) from voiture where duration<30 AND make="Audi" AND model="A4"
+---+---+---+---+---+---+---+---+---+---+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+---+---+---+---+---+---+---+---+---+---+
| 1 | SIMPLE | voiture | ALL | NULL | NULL | NULL | NULL | 1376949 | Using where |
+---+---+---+---+---+---+---+---+---+---+
select price from voiture where duration<30 AND make="Audi" AND model="A4"
+---+---+---+---+---+---+---+---+---+---+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+---+---+---+---+---+---+---+---+---+---+
| 1 | SIMPLE | voiture | ALL | NULL | NULL | NULL | NULL | 1376949 | Using where |
+---+---+---+---+---+---+---+---+---+---+
此查询在 phpMyAdmin 界面上执行大约需要 2 秒。我试图查看问题所在,删除 avg 函数会使查询持续约 0.0080 秒。
我问自己在 php 脚本中计算 avg 需要多长时间,但是有或没有 avg 的查询都需要大约 2 秒。
所以我决定采用我的 table 的所有值并在脚本中进行处理,所以我使用这个查询:
select * from voiture where duration<30 AND make="Audi" AND model="A4"
+---+---+---+---+---+---+---+---+---+---+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+---+---+---+---+---+---+---+---+---+---+
| 1 | SIMPLE | voiture | ALL | NULL | NULL | NULL | NULL | 1376949 | Using where |
+---+---+---+---+---+---+---+---+---+---+
在phpMyAdmin 界面,耗时0.0112 秒。但是在我的 php 脚本中,它需要 25 秒!
$timestart2=microtime(true);
$querysec='select * from voiture where duration<30 AND make="Audi" AND model="A4"';
$requestsec=mysql_query($querysec) or die(mysql_error());
$timeend2=microtime(true);
$time2=$timeend2-$timestart2;
$page_load_time2 = number_format($time2, 9);
这里是 table 结构:
CREATE TABLE `voiture` (
`carid` bigint(9) NOT NULL,
`serviceid` bigint(9) NOT NULL,
`service` varchar(256) NOT NULL,
`model` varchar(256) DEFAULT NULL,
`gearingType` varchar(256) DEFAULT NULL,
`displacement` int(5) DEFAULT NULL,
`cylinders` int(2) DEFAULT NULL,
`fuel` varchar(32) DEFAULT NULL,
`mileage` int(7) DEFAULT NULL,
`existFlag` tinyint(1) DEFAULT NULL,
`lastUpdate` date DEFAULT NULL,
`version` varchar(256) DEFAULT NULL,
`bodyType` varchar(256) DEFAULT NULL,
`firstRegistration` date DEFAULT NULL,
`powerHp` int(4) DEFAULT NULL,
`powerKw` int(4) DEFAULT NULL,
`vat` varchar(256) DEFAULT NULL,
`price` decimal(12,2) DEFAULT NULL,
`duration` int(3) DEFAULT NULL,
`pageUrl` varchar(256) DEFAULT NULL,
`carImg` varchar(256) DEFAULT NULL,
`color` varchar(256) DEFAULT NULL,
`doors` int(1) DEFAULT NULL,
`seats` int(1) DEFAULT NULL,
`prevOwner` int(1) DEFAULT NULL,
`co2` varchar(256) DEFAULT NULL,
`consumption` varchar(256) DEFAULT NULL,
`gears` int(1) DEFAULT NULL,
`equipment` varchar(1024) NOT NULL,
`make` varchar(256) NOT NULL,
`country` varchar(3) NOT NULL
)
carid 和 serviceid 有索引
为什么我的查询需要这么长时间才能执行?有什么办法可以改进吗?
为什么 phpMyAdmin 和我的 php 脚本的执行时间不同?
有很多可能的解决方案,您可以首先在数据库级别执行 is create index 这也可以缩短执行时间。
其次检查服务器,可能有一些进程会占用你的服务器资源,使你的服务器变慢。
您可以像这样使用 GROUP BY 使其更快
select AVG(price) from voiture where duration<30 AND make="Audi" AND model="A4" GROUP BY make
也可以为 make 列添加索引
ALTER TABLE `voiture` ADD INDEX `make` (`make`)
On the phpMyAdmin interface, it takes 0.0112 seconds. But in my php
script, it takes 25 seconds!
phpMyAdmin 界面为每个查询添加 LIMIT
。默认为 LIMIT 30
。
为了减少聚合查询的时间,您需要为您使用的每个条件创建索引(或者可能是一个复合索引)。
因此,请尝试为您的 model
、make
和 duration
字段创建索引。
此外,您的 table 过于反规范化了。你可以创建一对 table 来规范化它。
例如:Vendors(id, name)
、Models(id, name)
并修改您的 voiture
以具有 vendor_id
/model_id
字段而不是文本 make
/model
。
那么您的初始查询将如下所示:
select avg(t.price) from voiture t
INNER JOIN Models m ON m.id = t.model_id
INNER JOIN Vendors v ON v.id = t.vendor_id
where t.duration<30 AND v.name="Audi" AND m.name="A4"
它将扫描轻度查找 table 以查找文本匹配项,并使用带有索引 ID 的重度 table 进行操作。
我对脚本的执行时间有一些疑问。查询需要很多时间。这是查询:
select avg(price) from voiture where duration<30 AND make="Audi" AND model="A4"
+---+---+---+---+---+---+---+---+---+---+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+---+---+---+---+---+---+---+---+---+---+
| 1 | SIMPLE | voiture | ALL | NULL | NULL | NULL | NULL | 1376949 | Using where |
+---+---+---+---+---+---+---+---+---+---+
select price from voiture where duration<30 AND make="Audi" AND model="A4"
+---+---+---+---+---+---+---+---+---+---+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+---+---+---+---+---+---+---+---+---+---+
| 1 | SIMPLE | voiture | ALL | NULL | NULL | NULL | NULL | 1376949 | Using where |
+---+---+---+---+---+---+---+---+---+---+
此查询在 phpMyAdmin 界面上执行大约需要 2 秒。我试图查看问题所在,删除 avg 函数会使查询持续约 0.0080 秒。
我问自己在 php 脚本中计算 avg 需要多长时间,但是有或没有 avg 的查询都需要大约 2 秒。
所以我决定采用我的 table 的所有值并在脚本中进行处理,所以我使用这个查询:
select * from voiture where duration<30 AND make="Audi" AND model="A4"
+---+---+---+---+---+---+---+---+---+---+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+---+---+---+---+---+---+---+---+---+---+
| 1 | SIMPLE | voiture | ALL | NULL | NULL | NULL | NULL | 1376949 | Using where |
+---+---+---+---+---+---+---+---+---+---+
在phpMyAdmin 界面,耗时0.0112 秒。但是在我的 php 脚本中,它需要 25 秒!
$timestart2=microtime(true);
$querysec='select * from voiture where duration<30 AND make="Audi" AND model="A4"';
$requestsec=mysql_query($querysec) or die(mysql_error());
$timeend2=microtime(true);
$time2=$timeend2-$timestart2;
$page_load_time2 = number_format($time2, 9);
这里是 table 结构:
CREATE TABLE `voiture` (
`carid` bigint(9) NOT NULL,
`serviceid` bigint(9) NOT NULL,
`service` varchar(256) NOT NULL,
`model` varchar(256) DEFAULT NULL,
`gearingType` varchar(256) DEFAULT NULL,
`displacement` int(5) DEFAULT NULL,
`cylinders` int(2) DEFAULT NULL,
`fuel` varchar(32) DEFAULT NULL,
`mileage` int(7) DEFAULT NULL,
`existFlag` tinyint(1) DEFAULT NULL,
`lastUpdate` date DEFAULT NULL,
`version` varchar(256) DEFAULT NULL,
`bodyType` varchar(256) DEFAULT NULL,
`firstRegistration` date DEFAULT NULL,
`powerHp` int(4) DEFAULT NULL,
`powerKw` int(4) DEFAULT NULL,
`vat` varchar(256) DEFAULT NULL,
`price` decimal(12,2) DEFAULT NULL,
`duration` int(3) DEFAULT NULL,
`pageUrl` varchar(256) DEFAULT NULL,
`carImg` varchar(256) DEFAULT NULL,
`color` varchar(256) DEFAULT NULL,
`doors` int(1) DEFAULT NULL,
`seats` int(1) DEFAULT NULL,
`prevOwner` int(1) DEFAULT NULL,
`co2` varchar(256) DEFAULT NULL,
`consumption` varchar(256) DEFAULT NULL,
`gears` int(1) DEFAULT NULL,
`equipment` varchar(1024) NOT NULL,
`make` varchar(256) NOT NULL,
`country` varchar(3) NOT NULL
)
carid 和 serviceid 有索引
为什么我的查询需要这么长时间才能执行?有什么办法可以改进吗?
为什么 phpMyAdmin 和我的 php 脚本的执行时间不同?
有很多可能的解决方案,您可以首先在数据库级别执行 is create index 这也可以缩短执行时间。
其次检查服务器,可能有一些进程会占用你的服务器资源,使你的服务器变慢。
您可以像这样使用 GROUP BY 使其更快
select AVG(price) from voiture where duration<30 AND make="Audi" AND model="A4" GROUP BY make
也可以为 make 列添加索引
ALTER TABLE `voiture` ADD INDEX `make` (`make`)
On the phpMyAdmin interface, it takes 0.0112 seconds. But in my php script, it takes 25 seconds!
phpMyAdmin 界面为每个查询添加 LIMIT
。默认为 LIMIT 30
。
为了减少聚合查询的时间,您需要为您使用的每个条件创建索引(或者可能是一个复合索引)。
因此,请尝试为您的 model
、make
和 duration
字段创建索引。
此外,您的 table 过于反规范化了。你可以创建一对 table 来规范化它。
例如:Vendors(id, name)
、Models(id, name)
并修改您的 voiture
以具有 vendor_id
/model_id
字段而不是文本 make
/model
。
那么您的初始查询将如下所示:
select avg(t.price) from voiture t
INNER JOIN Models m ON m.id = t.model_id
INNER JOIN Vendors v ON v.id = t.vendor_id
where t.duration<30 AND v.name="Audi" AND m.name="A4"
它将扫描轻度查找 table 以查找文本匹配项,并使用带有索引 ID 的重度 table 进行操作。