让 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 版本。
希望有帮助。