1

このスクリプトの実行時間を短縮しようとしています。ループで約 1000 回、約 200 万レコードのデータベースにクエリを実行します。

foreach ($ids as $id){
    $stmt=$dbh->query("SELECT SQL_CACHE * FROM `ids` 
                WHERE $id BETWEEN `id_start` AND `id_end`");
    $rows[] = $stmt->fetch();
}

4 コアの 8 GB マシンでは永遠にかかります (約 800 秒!)。ID グループは重複せず、ID は実行ごとにいくつかの異なるグループからのものになる傾向があり、(id_start,id_end) と (id_end) の両方にインデックスを付けました。

キャッシュは状況を非常に改善します (同じ 1000 個の値を複数回実行するのはほんの数秒です) が、キャッシュされていないクエリを高速化するために何ができるか知りたいです。

EXPLAIN の出力例:

"id"    "select_type"   "table"     "type"  "possible_keys"     "key"               "key_len"   "ref"   "rows"  "Extra"
"1"     "SIMPLE"        "ids"       "range" "id_start,id_end"   "id_start,id_end"   "5"          ""     "52508" "Using index condition"

編集:「インデックス条件を使用する」の代わりに、「どこを使用するか」が表示されることがあります(よくわかりませんが、840771583 よりも高い ID 値からだと思います)なぜですか?

編集 2 : 完全な作成コード:

CREATE TABLE `ids` (
    `id_start` INT(10) UNSIGNED NULL DEFAULT NULL,
    `id_end` INT(10) UNSIGNED NULL DEFAULT NULL,
    `iso-639-1` VARCHAR(2) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
    `country_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
    `region_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
    `city_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
    `area_code` VARCHAR(16) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
    `timezone` VARCHAR(6) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
    UNIQUE INDEX `id_startid_end` (`id_start`, `id_end`),
    INDEX `id_end` (`id_end`),
    INDEX `country_name` (`country_name`),
    INDEX `region_name` (`region_name`),
    INDEX `city_name` (`city_name`),
    INDEX `area_code` (`area_code`),
    INDEX `iso-639-1` (`iso-639-1`),
    INDEX `timezone` (`timezone`)
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB;
4

2 に答える 2

1
It queries a database with about 2 million records about 1000 times on a loop:
                                                         ^^^^^^^^^^^^^^^^^^^^   

ここ

あなたの問題です。

確かに単一のクエリである必要があります。

また、キー バッファ サイズが十分かどうかを確認するために、mysql デーモンを微調整することも検討してください。

この質問は PDO とはまったく関係ありません。問題に対処するときは、不要な部分をすべて取り除いて、可能な限り絞り込む必要があります。クエリといえば、それをコンソールに入れてそこでプレイする必要があります。

于 2013-09-06T07:04:47.660 に答える