0

ユーザーテーブルには

id, email, password, gender, dob 

など。性別はデフォルトの null です。と を持つ別のテーブルuser_genderfirst_nameありgenderます。私のSQLクエリは、に基づいてユーザーを取得しUser、性別を選択しています。ユーザー テーブルは巨大で、約 300,000 行以上あります。以下のクエリを実行していますが、時間がかかりすぎています。このクエリを最適化するにはどうすればよいですか?-User_Genderfirst_name

select 
   count(*) 
from user u 
left outer join user_gender ug on ug.name = 
  case when locate(' ', u.name) > 0 then
     substring(u.name, 1,locate(' ', u.name))
  else
     u.name 
  end 
where 
  ug.gender != 'mf' and u.gender is null
4

3 に答える 3

6

まず、完全なリストラをお勧めします。300000 行が「中程度のデータ セット」サイズに達し始めています...

  • テーブルを適切 に正規化する
    • 複数の個別の値を格納する列を使用しないでください。特に名前列は、使用してはいけない良い例です。それが first_name と last_name の 2 つの列であるとします。
    • DavidB は男女分離について言及しました。これはまったくナンセンスです。少なくとも、誰もが性別を持っています... 不明ですが、常に可能性がありますNULL...
  • データフィールドを使用する代わりに(できれば数値!!)IDを使用します(特に名前のようなもの)
    • このように、名前が変更された場合 (IRL で発生する可能性があります)、1 行だけを更新する必要があります...
    • 2人が完全に同じ名前を持っている可能性さえあります...

次に、再構築後、インデックスを適用し、クエリの実行計画をチェックして、適切に最適化する必要があります。

于 2013-02-28T13:48:52.053 に答える
3

最初にこれら 2 つのテーブルの設計に取り掛かると、パフォーマンスの問題をより適切に解決するのに役立ちます。パフォーマンスの問題は、結合句で発生します。

case when locate(' ', u.name)>0 then substring(u.name, 1,locate(' ', u.name)) else u.name end

User テーブルに主キー (user_id) を使用し、これを user_gender テーブルに置き、それに応じて結合します。

また

古いデータベース設計を使用していて、user_id フィールドを追加または使用できない可能性があるため、一時的な first_name フィールドを使用し、結合句を使用して入力することができます。

update users u set u.first_name = case when locate(' ', u.name)>0 
then substring(u.name, 1,locate(' ',> u.name)) else u.name end

この後、クエリを次のように書き換えることができます

select count(*) from user u left outer join user_gender ug 
on ug.name=u.first_name 
where ug.gender != 'mf' and u.gender is null

これはクエリの実行を高速化するのに役立ちますが、とにかく主キーを追加/使用する最初の解決策を提案します。

于 2013-02-28T13:54:21.180 に答える
0

最初に指摘したいのは、クエリが正しく記述されていないことです。または、少なくとも、意図したとおりに動作していません。節のは!=where左外部結合を「元に戻す」ことです。私はあなたがon条項でそれを望んでいると思います。

のインデックスを使用するuser_gender(firstname, gender)と、このバージョンはかなり速く実行されるはずです。

select count(*) 
from (select u.*,
             (case when locate(' ', u.name) > 0 then substring(u.name, 1,locate(' ', u.name))
                   else u.name
              end) as FirstName
      from user u
     ) u
where not exists (select 1 from user_gender ug where ug.name = u.FirstName and ug.gender <> 'mf')

ユーザー テーブルを検索し、名を計算し、インデックスをチェックインして性別があるかどうかを確認する必要があります。

于 2013-02-28T14:16:38.787 に答える