MySQL に可能な限り多くの作業を行わせます。動作が効率的でない場合は、正しく設定されていない可能性があります (実行しようとしているクエリの適切なインデックス付けであるか、ソート バッファーの設定であるか)。
year
列にインデックスがある場合は、DISTINCT
効率的に使用できます。そうしないと、個別の行をフェッチするために全表スキャンが必要になります。MySQL ではなく PHP で個別の行を整理しようとすると、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
、273,505 回の個別のリストを取得するのに 1 分 40 秒かかります。オーバーヘッドのほとんどは、ネットワーク経由ですべてのレコードを転送するときに発生します。 . したがって、返されるデータ量の制限に注意してください。取得しようとしているデータの量をできるだけ低く抑えたいと考えています。
あなたの最終的なクエリについては:
select distinct line from car_cache
where year='$postyear' and make='$postmake'
order by line desc
それにも問題はないはずです。複合インデックスが にyear
ありmake
、場合によっては にインデックスがあることを確認してくださいline
。
最後に、読み取りテーブルに使用しているエンジンは InnoDB であり、サーバーは5.5.23-55-log Percona Server (GPL), Release 25.3
Percona Inc. による MySQL のバージョンです。
それが役立つことを願っています。