次のクエリについて考えてみます。
_SELECT
`locations`.`id` AS `location_id`,
`locations`.`address`,
`locations`.`lat`,
`locations`.`lng`,
`tickets`.`status_id`,
`customers`.`name`,
`tickets`.`id` AS `id`,
`tickets`.`updated_at` AS `updated_at`,
( 3959 * acos( cos( radians('39.78222851322262') ) * cos( radians( `lat` ) ) * cos( radians( `lng` ) - radians('-86.16299560000004') ) + sin( radians('39.78222851322262') ) * sin( radians( `lat` ) ) ) ) AS `distance`
FROM `locations`
RIGHT JOIN `tickets`
ON (`tickets`.`location_id` = `locations`.`id`)
LEFT JOIN `customers`
ON (`tickets`.`customer_id` = `customers`.`id`)
WHERE `tickets`.`client_id` = '20'
AND
(
`customers`.`name` LIKE '%Mahoney%'
OR `customers`.`email` LIKE '%Mahoney%'
OR `locations`.`address` LIKE '%Mahoney%'
)
HAVING `distance` < '5'
ORDER BY `distance`
LIMIT 200;
_
プロファイリングツールを使用して、このレポートを取得しました。
_Speed: 45.569 ms
Query analysis:
· Query: SIMPLE on tickets · Type: ALL · Rows: 160 (Using where; Using temporary; Using filesort)
· Query: SIMPLE on locations · Possible keys: PRIMARY · Key Used: PRIMARY · Type: eq_ref · Rows: 1
· Query: SIMPLE on customers · Possible keys: PRIMARY · Key Used: PRIMARY · Type: eq_ref · Rows: 1 (Using where)
_
これはMySQLデータベースです。すべてのテーブルはutf8_unicode_ciを備えたInnoDBです。各テーブルの主キーはid
と呼ばれ、インデックスが付いたint(11)
です。
tickets.location_id
_および/または_tickets.customer_id
_および/または_tickets.client_id
_にインデックスを追加すると、このクエリのパフォーマンスが向上しますか?最初に場所から選択するので、参照されている外部キーのインデックスが必要だと思います。私はここを読みます: インデックス、外部キーと最適化 MySQLはすべての外部キーのインデックスを必要としています。 InnoDBスキーマで外部キーを明示的に定義すると、パフォーマンスが向上しますか?そのような合計n00bであって申し訳ありません。助けてくれてありがとう!
explain
の出力の各行の「行」列を乗算します。Mysqlが暗黙的にFK列にインデックスを作成するという事実は、読み取りパフォーマンスが向上し、挿入/更新/削除のパフォーマンスが少し低下することを意味します(インデックス自体を更新する必要があるため)。
最後に、
私は最初に場所から選択しているので、...
完全に正しくはありません。物理処理は論理処理と同じではありません。オプティマイザーは、関係するテーブルを処理する順序(出力からわかるように、エンジンは最初にtickets
テーブルにアクセスします)と使用するアクセス方法を決定します。ヒントである程度制御できますが...
*サイドノート。 WHERE
句の記述方法:
WHERE `tickets`.`client_id` = '20'
AND
(
`customers`.`name` LIKE '%Mahoney%'
OR `customers`.`email` LIKE '%Mahoney%'
OR `locations`.`address` LIKE '%Mahoney%'
)
LEFT JOIN customers
をINNER JOIN
。*として動作させる
更新サイドノートを気にしないでください。複数のテーブルがあるOR
sがあることに注意していません。
お役に立てば幸いです。