は私が要求されたデータがかどうかが存在する、だから、どのパスがより効率的と高速であるかどうかを確認したい、私はそれからデータを引き出し億を超える記録、長期間および重いデータでは、どのPDO SQLクエリが高速ですか?表から
を持っていますもう一方? id
がPRIMARY (INT)
で、aid, rid
はほとんど測定可能とあなたはほぼ確実に等価です示しINDEXED (INT)
は私が要求されたデータがかどうかが存在する、だから、どのパスがより効率的と高速であるかどうかを確認したい、私はそれからデータを引き出し億を超える記録、長期間および重いデータでは、どのPDO SQLクエリが高速ですか?表から
を持っていますもう一方? id
がPRIMARY (INT)
で、aid, rid
はほとんど測定可能とあなたはほぼ確実に等価です示しINDEXED (INT)
二つの方法、であることを念頭に
$Query = '
SELECT n.id
FROM names n
INNER JOIN ages a ON n.id = a.aid
INNER JOIN regions r ON n.id = r.rid
WHERE id = :id
';
$stmt->prepare($Query);
$stmt->execute(['id' => $id]);
if ($stmt->rowCount() == 1) {
$row = $stmt->fetch();
......................
} else {
exit();
}
または
$EXISTS = 'SELECT EXISTS (
SELECT n.fname, n.lname, a.age, r.region
FROM names n
INNER JOIN ages a ON n.id = a.aid
INNER JOIN regions r ON n.id = r.rid
WHERE id = :id
LIMIT 1
)
';
$stmt->prepare($EXISTS);
$stmt->execute(['id' => $id]);
if ($stmt->fetchColumn() == 1) {
$stmt->prepare($Query);
$stmt->execute(['id' => $id]);
$row = $stmt->fetch();
......................
} else {
exit();
}
キープパフォーマンスの違い。
SELECT n.id
FROM names n
INNER JOIN ages a ON n.id = a.aid
INNER JOIN regions r ON n.id = r.rid
WHERE id = :id
names.id
は、そのテーブルの主キーです。主キーの参照は非常に高速です。
そして、それは、他の2つのテーブルに二次キーのルックアップを行いますと、それらのテーブルの他の列への参照がありませんので、それは、索引のみのアクセスとなります。
あなたはMySQLの最適化計画を分析するためにEXPLAINを使用する方法を学ぶ必要があります。これは、SQLクエリのパフォーマンスを向上させたいときはいつでも練習すべきスキルです。
は、我々は、各テーブルへのアクセスは、(あなたがあなたの質問であなたのSHOW CREATE TABLE
を提供しなかったけれども、私は、インデックスを想定しています)インデックスを使用していることがわかりhttps://dev.mysql.com/doc/refman/5.7/en/using-explain.html
mysql> explain SELECT n.id
-> FROM names n
-> INNER JOIN ages a ON n.id = a.aid
-> INNER JOIN regions r ON n.id = r.rid
-> WHERE id = 1;
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
| 1 | SIMPLE | n | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | Using index |
| 1 | SIMPLE | a | NULL | ref | aid | aid | 5 | const | 1 | 100.00 | Using index |
| 1 | SIMPLE | r | NULL | ref | rid | rid | 5 | const | 1 | 100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
を参照してください。
サブクエリは、最初のクエリの最適化プランと同じに見えますSELECT EXISTS(...)
mysql> explain SELECT EXISTS (
-> SELECT n.id
-> FROM names n
-> INNER JOIN ages a ON n.id = a.aid
-> INNER JOIN regions r ON n.id = r.rid
-> WHERE id = 1
-> LIMIT 1);
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+----------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+----------------+
| 1 | PRIMARY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
| 2 | SUBQUERY | n | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | Using index |
| 2 | SUBQUERY | a | NULL | ref | aid | aid | 5 | const | 1 | 100.00 | Using index |
| 2 | SUBQUERY | r | NULL | ref | rid | rid | 5 | const | 1 | 100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+----------------+
と第二の溶液と比較。同じ方法でインデックスを使用します。しかし、それはサブクエリに委ねられています。おそらく大きな違いはありませんが、それはもう一つのことです。
唯一の利点は、SELECT EXISTS...
クエリがtrue/falseの値を1行のみを返すことが保証されていることです。最初のクエリは、クエリのJOINに一致する数に応じて、ゼロ、1つ、または複数の行を含む結果セットを返すことがあります。違いはパフォーマンスの違いではありません(結果セットをクライアントに転送するのに時間がかかったり、クライアントで結果セットを保持するために大量のメモリを使用する行が多すぎる場合を除きますが)。あなたがそれをコードする方法。
年齢を正規化しないでください。それは単に空間と時間の無駄です。 age
(それは年であると仮定)は、1バイトのTINYINT UNSIGNED
(範囲:0 255)に収まるとJOIN
検索を避けます。 aid
は4バイトのINT
のように見えますが、これは数十億の異なる値を保持できます。何十億という異なる年月がありますか?
多分regions
を変更する価値があります。
最初のクエリでは、2つのJOINs
は何もしませんが、年齢と地域に行があることを確認します。それはおそらくです。
EXISTS
は、1つの行が見つかると停止します。従ってLIMIT 1
は非常に不必要です。
FYI問合せの最適化に関するヘルプを求める質問は、問合せの各表に対する「SHOW CREATE TABLE」の出力を含める必要があるため、データ型、索引および制約を推測する必要はありません。多くの人のようにスクリーンショットとしてではなく、テキストで投稿してください。 –