1

INSERT ON DUPLICATE KEY UPDATE各挿入が異なる列のセットを持つことができる約600のクエリを実行しています。

私が今やっている方法は、mysql_query(). 本当に遅いです。最大実行時間が 30 秒であるため、php スクリプトが停止します。

INSERT INTO table (columns) VALUES (values 1), (values 2), ..., (values n)各挿入が異なる列のセットを持つことができる必要があるため、使用できません。

準備されたクエリも調べましたが、私が見たところ、異なる列セットでも機能しないようです。

私はデータベースと MYSQL の初心者です。私は週末のプロジェクトとして何かをハッキングしているだけで、今はプロジェクトの最後の部分を機能させたいだけです。これを適切な方法で行わなかったことをお詫び申し上げます。(非推奨のphp mysql関数も使用して申し訳ありません。)多分私は寝て、後でこれを書き直すべきです。それを行う適切な方法は何ですか?

編集:ここにテーブルタイプに関するいくつかの情報があります

-- phpMyAdmin SQL ダンプ
-- バージョン 3.5.1
-- http://www.phpmyadmin.net
--
-- ホスト: ローカルホスト
-- 生成時間: 2012 年 7 月 22 日午後 9 時 59 分
-- サーバー バージョン: 5.5.24-log
-- PHP バージョン: 5.3.13

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";

--
-- データベース: `トレーラーベイ`
--

-- ------------------------------------------------ --------

--
-- テーブル `movies` のテーブル構造
--

CREATE TABLE IF NOT EXISTS `movies` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `imdb` int(7) NOT NULL,
  `title` text COLLATE utf8_unicode_ci,
  `releasedate` 日付 DEFAULT NULL,
  `enlistdate` datetime NOT NULL,
  `runtime` 時間 DEFAULT NULL,
  `トレーラー` テキスト COLLATE utf8_unicode_ci NOT NULL,
  `plot` テキスト COLLATE utf8_unicode_ci,
  `cover` テキスト COLLATE utf8_unicode_ci NOT NULL,
  主キー (`id`)、
  UNIQUE KEY `id` (`id`),
  UNIQUE KEY `imdb` (`imdb`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1145 ;
4

3 に答える 3

1

テーブルに非常に多くの列を含めることはできないと思います。そのため、オン/オフの組み合わせが非常に多くなります。

したがって、各行について、その列の組み合わせを抽出し (たとえば、フィールドをアルファベット順に並べることができます)、その構造をキーとして使用できます。

// $tuple has been sorted based on keys

$syndrome = implode(',', array_keys($tuple));

$values = array_values($tuple);    

if (isset($big_inserts[$syndrome]))
    array_push($big_inserts[$syndrome], $values);
else
    $big_inserts[$syndrome] = array($values);

ループの最後に$big_inserts、特定の数のキーを持つ配列が表示されます。各キーは、複数の挿入に適した一連の値の配列をマップします。

本当に不運でない限り、「複数の挿入」は、最初に行った個々の挿入よりもはるかに少なくなります。すべての挿入に同じ列がある場合、big_inserts には 1 つのキーしかなく、すべてのタプルを保持します。

ここで、big_inserts を循環させ、すべてのキーに対してステートメントを準備できます。PDO に送信される値の配列は、 のすべてのタプルを連結したもの$big_inserts[$key]です。

foreach($big_inserts as $fields => $lot)
{
    $SQL = "INSERT INTO table ($fields) VALUES ";
    // I need a (?.?.?---) tuple
    $tuple = '('.implode(',', array_fill(0, count($lot[0]), '?')).')';
    // How many tuples are in a lot?
    $SQL .= implode(',', array_fill(0, count($lot), $tuple));
    $values = array();
    foreach($lot as $set)
        $values = array_merge($values, $set);
    // Now $SQL has all the '?'s, and $values contains all the values.
    // Run the statement.
 }

これで十分でない場合は、ステートメントをチャンクに分割し、それらをセッションに保存し、各チャンクを順番に実行する必要があります。別のテーブルを使用して、「マルチラウンドトリップ」トランザクションをシミュレートする場合があります (接続が失われた場合/ユーザーがブラウザーを閉じた場合)。 / チャンクの半分がすでに実行されていて、残りの半分がまだ残っているもの. 同じ構造を持つテーブルに直接 INSERT を使用し、テーブルの準備ができたら、トランザクション内で 1 つの INSERT INTO ... SELECT FROM を実行し、補助を削除しますコミット後のテーブル。

それらが単純なINSERTである場合、いくつかのインデックスを一時的に無効にしてみますが、ON DUPLICATE KEY UPDATEのためにそれらに依存しているため、これはうまくいきません。

于 2012-07-22T22:02:12.117 に答える
0

一度に 50 個の挿入に分割し、12 個のファイルに分割して順番に実行するだけです。完了時に次のものにリダイレクトする単純な JavaScript。

1 回限りの取引であれば、それが最も簡単な解決策かもしれません。

それ以外の場合は、いくつかのサンプル コードを投稿して、より役立つ回答を提供できるようにします。

于 2012-07-22T21:48:35.257 に答える
0

挿入は mysql トランザクションで実行されていますか? そうでない場合は、これによりパフォーマンスが向上する可能性があります。

http://kevin.vanzonneveld.net/techblog/article/improve_mysql_insert_performance/

于 2012-07-22T21:56:09.610 に答える