0

私は MySQL にあまり慣れていませんが、それよりもはるかに高速になる可能性があると思います。

ここに私のテーブルがあります:

CREATE TABLE `crashes` (
`id` int(11) NOT NULL AUTO_INCREMENT,
 `added_date` int(11) NOT NULL,
 `status` int(11) NOT NULL,
 `issue_id` varchar(32) NOT NULL,
 `report_id` text NOT NULL,
 `app_version_code` text NOT NULL,
 `app_version_name` text NOT NULL,
 `package_name` varchar(80) NOT NULL,
 `package_name_id` tinyint(4) NOT NULL,
 `file_path` text NOT NULL,
 `phone_model` text NOT NULL,
 `android_version` text NOT NULL,
 `build` text NOT NULL,
 `brand` text NOT NULL,
 `product` text NOT NULL,
 `total_mem_size` int(11) NOT NULL,
 `available_mem_size` int(11) NOT NULL,
 `custom_data` text NOT NULL,
 `stack_trace` text NOT NULL,
 `initial_configuration` text NOT NULL,
 `crash_configuration` text NOT NULL,
 `display` text NOT NULL,
 `user_comment` text NOT NULL,
 `user_app_start_date` text NOT NULL,
 `user_crash_date` text NOT NULL,
 `dumpsys_meminfo` text NOT NULL,
 `dropbox` text NOT NULL,
 `logcat` text NOT NULL,
 `eventslog` text NOT NULL,
 `radiolog` text NOT NULL,
 `is_silent` text NOT NULL,
 `device_id` text NOT NULL,
 `installation_id` text NOT NULL,
 `user_email` text NOT NULL,
 `device_features` text NOT NULL,
 `environment` text NOT NULL,
 `settings_system` text NOT NULL,
 `settings_secure` text NOT NULL,
 `shared_preferences` text NOT NULL,
 `application_log` text NOT NULL,
 `media_codec_list` text NOT NULL,
 `thread_details` text NOT NULL,
 `user_ip` text NOT NULL,
 PRIMARY KEY (`id`),
 KEY `package_name_id` (`package_name_id`)
) ENGINE=MyISAM AUTO_INCREMENT=202364 DEFAULT CHARSET=utf8

ご覧のとおり、200k 行でいっぱいです。added_date行(unix タイムスタンプ、int(11))、およびその日の行数を取得したいと思います。

そこで、日付、曜日 (YMD として)、およびカウントを選択します。

SELECT date_format(from_unixtime(added_date), '%Y-%c-%d') as date, added_date, count(*) as nb_crashes FROM crashes WHERE package_name = 'net.bicou.redmine' GROUP BY date ORDER BY date ASC

とても遅いです!私のホストの専用mysqlサーバーでほぼ1.5秒。

だから私は物事を少し最適化できると考えました: である package_name_id を追加しtinyintましpackage_namepackage_nameINDEXMySQL をより高速に参照できるようにしました。
結果:0.9秒 それははるかに優れていますが、それでも私が期待しているパフォーマンスからは外れています!

どうすれば最適化できますか?各行に日付を作成すると、グループ化は非常に高価になります。ただし、これを高速化する方法がわかりません...

編集:

テーブルを更新するために私がしたことは次のとおりです。

ALTER TABLE  `crashes` ADD  `temp` DATETIME NOT NULL
UPDATE crashes SET temp = FROM_UNIXTIME( added_date )
ALTER TABLE  `crashes` ADD INDEX (  `temp` )

更新されたクエリは次のとおりです。

SELECT added_date, count(*) as nb_crashes FROM crashes WHERE package_name_id=3 GROUP BY year(temp),month (temp),dayofmonth(temp) ORDER BY temp ASC

実行時間はまだ約 1 秒です...何か間違ったことをしましたか?

4

3 に答える 3

2

日付のような方法でそのフィールドに対してクエリを実行する必要がある場合は、UNIX タイムスタンプ値を使用しないでください。日付、日時、またはタイムスタンプ フィールド タイプを使用する必要があります。

なんで?

特定の日付のクエリ結果や日付ごとにレコードをグループ化するようなことをしたい場合は、常に を使用FROM_UNIXTIME()する必要があるためです。この関数呼び出しは、並べ替え、結合、WHERE フィルター、グループなどに使用しようとしている場合、日付値に任意の種類のインデックスを使用することを防ぎます。適切な使用以外にクエリを改善するためにできることはありません。データ型を選択し、並べ替え、フィルター、結合、グループなどに使用するフィールドにインデックスを付けます。

実際、DB での UNIX タイムスタンプの使用は、PHP でこの形式の日付を扱う方が簡単だと考えている経験の浅い PHP 開発者によって急増しているようです (日付/日時 DB 出力を PHP で UNIX タイムスタンプに変換するのが面倒なのか、または、dateTime および dateInterval PHP クラスを使用して、PHP で日付を簡単に操作する方法を理解していません)。

私の提案は、この習慣を今すぐ破り、MySQL で日付/日時フィールドを操作する方法を学び始めることです。

テーブル DDL を見ることをお勧めするもう 1 つのことは、おそらくそこでのテキスト フィールドの使用を再検討する必要があるということです。これらのケースのほとんどは、varchar フィールドの方が適しているように見えます。

于 2013-09-11T18:20:06.300 に答える
0

package_name列と列の両方にインデックスを作成できadded_dateます。また、 byの代わりにORDER BYorder byに変更してください。おそらくファイルソートのステップが必要になるからです。added_datedatedate

いずれにせよEXPLAIN、クエリをより適切に診断するのに役立ちます。

于 2013-09-11T18:28:26.743 に答える