2017-05-08 9 views
1

をドロップする推定時間は、我々は次のように定義されたかなり最適化されていないテーブルを持っている:MySQLの - インデックス

CREATE TABLE `Usage` (
`TxnDate` varchar(30) DEFAULT NULL, 
`TxnID` decimal(13,2) NOT NULL, 
`UserID2015` varchar(20) DEFAULT NULL, 
`UserRMN` decimal(13,0) DEFAULT NULL, 
`CustomerNo` decimal(13,0) DEFAULT NULL, 
`OperatorName` varchar(50) DEFAULT NULL, 
`AggregatorName` varchar(30) DEFAULT NULL, 
`TransAmount` decimal(10,2) DEFAULT NULL, 
`MMPLTxnID` decimal(13,0) DEFAULT NULL, 
`ProductType` varchar(30) DEFAULT NULL, 
`YearMonthRMN` varchar(50) DEFAULT NULL, 
PRIMARY KEY (`TxnID`), 
UNIQUE KEY `TxnID` (`TxnID`) USING BTREE, 
KEY `TxnDate` (`TxnDate`), 
KEY `OperatorName` (`OperatorName`), 
KEY `AggregatorName` (`AggregatorName`), 
KEY `MMPLTxnID` (`MMPLTxnID`), 
KEY `ProductType` (`ProductType`), 
KEY `UserRMN` (`UserRMN`), 
KEY `YearMonthRMN` (`YearMonthRMN`) USING BTREE, 
KEY `CustomerNo` (`CustomerNo`) USING BTREE 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 

テーブルはabotu 170Mレコードを持っています。

プライマリキーを削除し、代わりに自動番号プライマリキーを追加します。これまでのところ、指数の低下は2時間を要した。

インデックスを削除するのに時間がかかりすぎる理由は何ですか?

インデックスを削除する時間はどのように見積もりますか?

オートナンバーを追加すると、テーブルをソートする時間を見積もる必要がありますか?これは新しいオートナンバーインデックスでは必要ありませんか?

答えて

3

インデックスを削除するだけでなく、プライマリキーを削除することもできます。

通常、InnoDBテーブルはプライマリキーに基づいてクラスタ化インデックスとして格納されるため、プライマリキーを削除すると、セカンダリユニークキーまたはその自動生成キーのいずれかを使用する新しいテーブルを作成する必要がありますクラスタードインデックス。

私はかなりの量のMySQLコンサルティングを行っています。これにはどのくらいの時間がかかりますか?よくある質問です。

サーバー上に新しいクラスタード・インデックスを作成するのにかかる時間は長くかかります。これは予測するのが難しいです。サーバのCPUの速さ、ストレージの速さ、並行して実行される他の負荷の大きさ、CPUとI/Oの帯域幅と競合するなど、いくつかの要因によって異なります。

つまり、私の経験では、どれくらい時間がかかるかを予測することはできません。

テーブルは、新しいクラスタ化インデックスとしてTxnIDで再構築されます。これは、偶然に主キーと同じです。しかし、明らかにMySQL Serverは、この特別なケースをインプレース変更を行うためのショートカットを使用できるものとして認識しません。

テーブルには8つの他の2次インデックスもあり、そのうち5つはvarcharsです。テーブルの再構成中にそれらのインデックスを構築する必要があります。これは、クラスタ化インデックスに加えて、それらのインデックスを構築するための多くのI/Oです。これは、時間がかかる可能性が高いです。

新しい自動インクリメントプライマリキーを追加すると、同様のプロセスが実行されます。古いプライマリキーを削除して、新しい自動インクリメントプライマリキーを1つのALTER TABLEステートメントに作成すると、時間が節約できました。

+0

これはAmazon RDSにあるので、少なくともインデックスサイズのログ領域にメインメモリをプロビジョニングできますか? – jdog

+0

インデックスの作成は、通常、メモリではなくI/Oパフォーマンスによって制限されます。 –

+0

これは大丈夫ですが、おおよそ次のように計算できます。メモリにインデックス付きの列をソートするにはxGBが必要で、IO制約がある列を読み取るのにx時間が必要ですか?だから私は一時的に利用可能な最大のIOと十分なメモリを割り当てることができるので、ディスクへのスワッピングでソーティングは起こりません。 – jdog

2

(私はビルの答えに同意し、ここでより多くのコメントがあります。)

私はプロセスを強制終了してAUTO_INCREMENTどの利点があるかどうかを再考するでしょう。

"本当の"質問に疑問を抱くようにしようとしています。この場合、それはAUTO_INCREMENTが必要です。詳しく教えてください。

現在のPRIMARY KEYは6バイトです。新しいPKは、INTの場合は4バイト、BIGINTの場合は8バイトになります。したがって、ディスクスペースの使用率を大幅に削減または削減できます。

TxnIDによる検索は、AIを経由しているために遅くなります。 TxnIDUNIQUEで、nullでないため、最適な「自然な」PKのように見えます。

PK ユニークキーなので、UNIQUE(TxnID)は完全に冗長です。 DROPpingこれは何も失うことなくスペースを節約します。それが私が持っていた主な勧告です(ただスキーマを見ています)。

本質的にすべての列がNULLである表を見ると、デザイナーは列のヌルネスについて意識的な決定をしていないことが疑わしいです。

DECIMAL(13,2)は多くのドルまたはユーロになりますが、PKとしては非常に珍しいことです。どうしたの?

latin1?グローバリゼーションの計画はありませんか?

多くの単一列インデックスがありますか? WHERE a=1 AND b=2は複合体を求めていますINDEX(a,b)

戻る時間を推定する...

ALTERは8-9インデックスを再構築した場合、何それはディスクソートでできる行う必要があります。これには、RAMに関係する効率的なディスクベースの並べ替えを使用して、ディスクに書き込む作業と、並べ替えられた結果を読み込んでインデックスを再作成する作業が含まれます。ソートはO(log N)で、非線形にします。これにより、時間を予測するのが難しくなります。 MariaDBの一部の新しいバージョンは、残りの時間を見積もってになりますが、私はそれを信用しません。

二次インデックスには、インデックスとなる列と、PKの他の列が含まれます。 の各インデックスは、テーブルで約5-10GBのディスク容量を占有します。このは、IOPなどに変換するのに役立ちます。ただし、RAMをあまり使わないと仮定すると、索引を再構築するソートでは5〜10GBが数回読み返されます。

複数のALTERsを実行する場合は、1つのALTER文で実行します。そうすれば、すべての作業(特にセカンダリ索引の再構築)を一度だけ行う必要があります。

使用しているバージョンがわかりません。古いバージョンでは1つの選択肢が表示されます: "COPY":新しいテーブルを作成します。データをコピーする。索引を再構築する。名前を変更します。新しいバージョンではインデックス "INPLACE"を扱うことができます。注:PRIMARY KEYを変更するには、コピー方法が必要です。興味がある人々のために

+0

コメントありがとうございます。これは、インドからの取引、すなわち小数点のサイズのデータ​​ベースです。データのインポートプロセスは標準以下であるため、オペレータはTxnIdを信頼できず、インポート作業を識別するために自動番号が必要です。私はこのデータベースを退職させようとしていますが、私たちはより新しい、より良い設定をしていますが、私たちはまだそこにいません。さらに、より新しいデータベースを最適化するのに役立つので、私は提供された計算を感謝します。 MySQLは5.7 – jdog

+0

ですが、より多くの情報があっても、計算はおおよそのものに過ぎません。多くのものがBTreesの成長/縮小を引き起こします。それでも、私は5-10GBがほぼ正しいと思います。 'latin1'は多くのインド言語のどれも '正しく'格納できないことを意味します。新しい設定にはutf8mb4(またはutf8)を使用する必要があります。 –

0

  • これは、格納されたデータの30ギガバイトとアマゾンオーロラ上で実行されます。 IOPSがどのようにプロビジョニングされているかについての情報は見つかりませんでしたが、最悪の場合、90IOPSが一貫して利用可能になると思いました。 10GBを書き込んだり書き込んだりするには約4時間かかります。

  • alter tableを実行する前にインスタンスをdb.r3.8xlargeにアップグレードしました。

  • は、その後、それが予想よりもはるかに優れて1時間21メートルを、取った

    alter table `Usage` drop primary key, add id bigint auto_increment primary key 
    

を走りました。

関連する問題