查询执行时间问题

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

为了减少聚合查询的时间,您需要为您使用的每个条件创建索引(或者可能是一个复合索引)。

因此,请尝试为您的 modelmakeduration 字段创建索引。


此外,您的 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 进行操作。