6

在这种情况下,哪种方法或多种方法的执行速度最快?

$year = db_get_fields("select distinct year from car_cache order by year desc");

或者

$year = db_get_fields("select year from car_cache");
$year = array_unique($year);
sort($year);

我听说 mysql 上的 distinct 对大型查询有很大的性能影响,并且该表可以有一百万行或更多行。我想知道哪种数据库类型组合(Innodb 或 MyISAM)也最有效。我知道许多优化都非常依赖查询。Year 是一个无符号数字,但其他字段是不同长度的 varchar,我知道这也可能会有所不同。如:

$line = db_get_fields("select distinct line from car_cache where year='$postyear' and make='$postmake' order by line desc");

我读到使用新的 innodb 多键方法可以非常快速地进行这样的查询。但是 distinct 和 order by 子句对我来说是危险信号。

4

1 回答 1

3

让 MySQL 做尽可能多的工作。如果它的工作效率不高,那么事情可能没有正确设置(无论是您尝试运行的查询的正确索引,还是带有排序缓冲区的设置)。

如果您在列上有索引year,那么使用DISTINCT应该是有效的。如果不这样做,则需要进行全表扫描才能获取不同的行。如果您尝试在 PHP 而不是 MySQL 中整理不同的行,那么您(可能)将更多数据从 MySQL 传输到 PHP,并且 PHP 在消除重复之前消耗更多内存来存储所有这些数据。

这是我拥有的开发数据库的一些示例输出。另请注意,此数据库位于网络上执行查询的不同服务器上。

SELECT COUNT(SerialNumber) FROM `readings`;
> 97698592

SELECT SQL_NO_CACHE DISTINCT `SerialNumber`
FROM `readings`
ORDER BY `SerialNumber` DESC
LIMIT 10000;
> Fetched 10000 records.  Duration: 0.801 sec, fetched in: 0.082 sec

> EXPLAIN *above_query*
+----+-------------+----------+-------+---------------+---------+---------+------+------+-----------------------------------------------------------+
| id | select_type | table    | type  | possible_keys | key     | key_len | ref  | rows | Extra                                                     |
+----+-------------+----------+-------+---------------+---------+---------+------+------+-----------------------------------------------------------+
|  1 | SIMPLE      | readings | range | NULL          | PRIMARY | 18      | NULL |   19 | Using index for group-by; Using temporary; Using filesort |
+----+-------------+----------+-------+---------------+---------+---------+------+------+-----------------------------------------------------------+

如果我尝试相同的查询,除了将SerialNumber列替换为非索引的列,那么它将永远运行,因为 MySQL 必须检查所有 9700 万行。

一些效率与您期望返回的数据量有关。如果我稍微修改上述查询以对time列进行操作(读取的时间戳),则需要 1 分 40 秒才能获得 273,505 次的不同列表,其中大部分开销是通过网络传输所有记录. 因此,请记住您返回的数据量的限制,您希望将尝试获取的数据保持在尽可能低的水平。

至于您的最终查询:

select distinct line from car_cache
where year='$postyear' and make='$postmake'
order by line desc

这也应该没有问题,只要确保你有一个复合索引 onyear并且make可能有一个索引 on line

最后一点,我用于读数表的引擎是 InnoDB,我的服务器是:5.5.23-55-log Percona Server (GPL), Release 25.3这是 Percona Inc. 的 MySQL 版本。

希望有帮助。

于 2012-07-31T18:34:04.183 回答