1

データベースから場所 (都市、州) を選択する作業を行っています。問題は、クエリの実行が少し遅く、高速化する方法がわからないことです。例えば:

SELECT CONCAT_WS(', ', city, state) as location, AVG(latitude), AVG(longitude) 
FROM places
WHERE city='New York' AND state='NY'
GROUP BY location

データベースがきれいな連結されたバージョンの場所を返すようにするため、場所に関係なく CONCAT が発生します (代わりにコードでこれを行う理由がない限り)。たとえば、「ニューヨーク、ニューヨーク」などです。実際には、3 番目の列が混在することがあります (郵便番号)。私はMySQLで実行しています。

このクエリを最適化する最善の方法は何ですか?

また、二次的な質問として、「DISTINCT」を追加すると、何らかの方法でクエリが遅くなりますか? 例えば:

SELECT DISTINCT CONCAT_WS(', ', city, state) as location, AVG(latitude), AVG(longitude) 
FROM places
WHERE city='New York' AND state='NY'
GROUP BY location

(現在これをやっていますが、この質問をする過程で、GROUP BY句のためにDISTINCTは不要であることに気付きました;しかし、不要なので、それは何か違いがあるのだろうか、私はクエリを高速化するためにボートを揺さぶる必要があります。)

編集: 都市、州、および郵便番号に関するインデックスが既にあります。加えて、それらの組み合わせ (都市、郵便番号、および州/郵便番号のみ)。

4

4 に答える 4

4

で複合インデックスを作成し、(state, city)クエリを次のように書き換えます。

SELECT  CONCAT_WS(', ', city, state) AS location, AVG(latitude), AVG(longitude) 
FROM    places
WHERE   state='NY'
        AND city='New York'
GROUP BY
        state, city

このクエリでは、GROUP BY句を省略できることに注意してください。

SELECT  'New York, NY' AS location, AVG(latitude), AVG(longitude) 
FROM    places
WHERE   state='NY'
        AND city='New York'

ただし、このクエリにはまだ必要です。

SELECT  CONCAT_WS(', ', city, state) AS location, AVG(latitude), AVG(longitude) 
FROM    places
WHERE   state='NY'
GROUP BY
        state, city
于 2009-07-31T12:40:27.457 に答える
2

おかしな話ですが、データベースに関して人々が抱える問題のほとんどは速度であり、ストレージ要件ではありません。それはあなたに何かを伝えるはずです:-)

以前にもこのような問題があり、何度も言いましたが、行ごとの関数は一般的にうまくスケーリングしません。それらを修正するために私たちが見つけた最良の方法は、挿入/更新トリガーを使用することです (MySQL にこれらがあると仮定しています)。

pretty_city_state (または何でも) を呼び出す別の列を作成し、行を挿入または更新するたびにトリガーが都市と州からデータを入力するようにします。次に、その上にインデックスを作成します。

これは、一般に、データベースの行が書き込まれるよりもはるかに頻繁に読み取られるという事実を利用しています (特にこの場合)。書き込み時にその列を評価することにより、読み取り (おそらく数百万) ではなく、書き込み (数千) のコストを負担します。そして、pretty_city_state は都市または州のいずれかが変更されたときにのみ変更されるため、それを負担する必要がある場合の書き込みです。すべての選択で連結を行うと、労力が無駄になります。

それを試して違いを測定してください - あなたの選択がトリガーの最小限のコストで叫ぶことがわかると確信しています (データベース内にすべての都市と州があれば、そのコストは完全に消えます.

はい、私はこれが 3NF を破ることを知っています。自分が何をしているのかわかっている場合は、パフォーマンス上の理由からそうしてもまったく問題ありません。

クエリは次のように実行できます。

SELECT pretty_city_state as location, AVG(latitude), AVG(longitude) 
FROM places
WHERE city='New York' AND state='NY'
GROUP BY pretty_city_state

または、クエリを開始する前に都市と州を連結できれば、さらに高速になる可能性があります (推測しないでください)。

SELECT pretty_city_state as location, AVG(latitude), AVG(longitude) 
FROM places
WHERE pretty_city_state ='New York, NY'
GROUP BY pretty_city_state
于 2009-07-31T12:53:26.080 に答える
0

このようなクエリを最適化する 1 つの方法は、これらの列をインデックス列として設定することです。そうすれば、ツリーまたはハッシュに基づいて簡単にソート/グループ化できます。また、文字列の連結にもいくつかの意味がある場合があります。

于 2009-07-31T12:37:56.130 に答える
0

フィールド「city」と「state」にインデックスを追加すると役立ちます。

また、各フィールドのカーディナリティ (個別の値の数)、MySQL のバージョン、テーブル エンジン、およびその他のパラメーターによっては、WHERE 句を逆にすると、クエリの実行時間に影響を与える可能性があります。私は試してみたい:

WHERE state='NY' AND city='New York'
于 2009-07-31T12:43:30.453 に答える