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 の個別は、大規模なクエリのパフォーマンスに大きな影響を与えると聞いたことがあります。このテーブルには、100 万行以上の行が含まれる可能性があります。Innodb と MyISAM のどちらのデータベース タイプを組み合わせるのが最適かを考えてみました。多くの最適化がクエリに大きく依存していることは知っています。年は符号なしの数値ですが、他のフィールドはさまざまな長さの 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効率的に使用できます。そうしないと、個別の行をフェッチするために全表スキャンが必要になります。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 |
+----+-------------+----------+-------+---------------+---------+---------+------+------+-----------------------------------------------------------+

列をインデックス化されていない列に置き換えることを除いて、同じクエリを試みると、SerialNumberMySQL は 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.3Percona Inc. による MySQL のバージョンです。

それが役立つことを願っています。

于 2012-07-31T18:34:04.183 に答える