KEYで分割された顧客のInnoDBテーブルがあり、各パーティションは1つの米国の州です。私は電話番号のインデックスを持っていて、パフォーマンスは素晴らしいです。また、指定された米国の州の姓でSELECTする必要があります。姓と状態のインデックスを作成する必要がありますか、それともテーブルがすでに状態によってパーティション分割されているため、それを行う意味はありませんか?
InnoDBはどのパーティションがどの状態であるかをすでに知っているはずであり、そのパーティション内の姓に一致するすべての行を見つけるだけでよいので、それは不要なスペースを消費しますか?
結合は何もしていません...これは、次のような単純なクエリの場合のみです。
SELECT * FROM table WHERE lastname = "Smith" AND state="NY"
lastname
とおそらくstate,lastname
を含むインデックスを作成する必要があります。
考えてみてください。パーティション内の姓で検索するクエリを計画するようにクエリオプティマイザーに義務付けるものは何ですか?唯一の処置は、正しいパーティション内での全表スキャンです。
アメリカの50州を想定しましょう(プエルトリコ、グアム、米国連邦、または保護領)
100万行ある場合、状態ごとに平均すると20,000行になります。姓の20,000秒のテーブルスキャンはそれほど悪くないかもしれません。しかし、我々は米国について話している。ニューヨーク、カリフォルニア、テキサス、フロリダに巨大な数が住んでいる可能性があります。少数はロードアイランド、アイダホ、ワイオミング、モンタナに居住します。全表スキャンによる検索時間は大幅に異なります。これに照らして、各州内の名前に索引を付けることは有益です。
2つのインデックスを提案します
MySQLのパーティショニング に公平を期して、クエリオプティマイザーがWHERE句に基づく1つのパーティションのみからデータ検索をナビゲートできるほどスマートである場合は、(state,lastname)
は不要かもしれません。それでも、lastname
でインデックスを作成する必要があります。このように、各パーティションはラストネームでインデックスを作成しています。
(state,lastname)
でのインデックス付けに関する私の最初の提案は、実際のインデックス付け方法 MERGEストレージエンジンで結合されたMyISAMテーブル に基づいています。
MERGEテーブルに関する私の過去の例は次のとおりです。
Jan 04, 2012
: mysqlの多すぎるテーブルから列を取得するJan 15, 2012
: 個別のテーブルか、1つの巨大なテーブルを分割しますか?テーブルのパーティション分割が実装されているため、lastnameのインデックス付けで十分です。実際、電話番号にインデックスが付けられており、パフォーマンスが優れていたと述べたことを思い出してください。つまり、ラストネームのインデックス付けも同様に役立つはずです。
パーティショニングなし
あなたが言ったことに基づいて、PARTITIONing
はテーブルにとって役に立たないです。代わりに、パーティション化されていないテーブルを
_INDEX(phonenumber),
INDEX(lastname, state) -- in either order
_
2つのクエリに最適です。電話番号によるパーティション化されていないルックアップは、50ではなく1か所だけを探す必要があるため、より優れています(さらに、結果をマージし、そのうち49は空です)。
with PARTITION BY KEY(state)
_INDEX(phonenumber), -- checks 50 places
INDEX(last_name) -- sufficient...
_
_WHERE lastname = "Smith" AND state="NY"
_は、最初に1つのパーティションを「整理」し、次にNYパーティションに固有のインデックスを検索します。インデックスにstate
を追加しても(最初または最後のいずれか)、利点はなく、インデックスが大きくなります(わずかな欠点)。
ところで、カリフォルニアはアメリカの人口の12%を持っています。ワイオミングは0.2%です。そのBTreeはそれ以上深くない可能性があるため、このような不均衡による影響は最小限です。
各パーティションには「空き」スペースがたくさんあります。テーブルの全体的な空き領域は、パーティション化されていないテーブルの約50倍です。その理由だけでも、少なくとも100万行ある場合を除いて、パーティション分割を気にしないでください。