質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
INSERT

INSERTとは、行を追加する、コンピュータのデータベース言語SQLにおけるデータ操作言語(DML)ステートメントの1つである

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

4回答

12200閲覧

バルクインサートは実コード上で使っても良い?

nnahito

総合スコア2006

INSERT

INSERTとは、行を追加する、コンピュータのデータベース言語SQLにおけるデータ操作言語(DML)ステートメントの1つである

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

1グッド

2クリップ

投稿2018/12/27 02:18

知りたいこと

SQLのバルクインサートは、PHPなどの実コード上で利用して良いのか?

この疑問に至った理由

どこかで聞いた記憶があるがそのソースが見つからず、「記憶違いかどうか」を確認したいので、
お知恵をお貸しいただけると嬉しいです。

記憶

バルクインサートはDBロックが掛かるので、実コードでは使わない方が良い
バルクインサートは高速ですが、DBロックが掛かるので、実コード上ではあまり使わないほうが良く、
遅くともinsert文を一つずつ実行していくほうが良い。
バルクインサートは、直接値を入れるときやバッチ処理で使う。

と、本か何かで知った記憶があります。
この記憶は間違いなのでしょうか?それとも正しいのでしょうか?

ご存知の方がいらっしゃいましたら、ご教示いただけますと幸いです。

set0gut1👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

PHPということなので、MySQLと仮定して。

MySQLでINSERTのデッドロックに嵌る人を1人でも減らすために
MySQL(InnoDB)でのDeadLock調査

MySQLのトランザクション分離(ISOLATION)レベルが、REPEATABLE READ(デフォルトがREPEATABLE READ)では、ファントムリード回避のためにネクストキーロックによるインデックス挿入時のロックが発生する可能性があります。

ファントムリードが問題にならない作りなら、ISOLATIONレベルをREAD COMMITEDにすれば発生はしないようです。

投稿2018/12/27 02:56

編集2018/12/27 04:09
sazi

総合スコア25300

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nnahito

2019/01/03 13:02

ご回答有り難うございます! まず、私のエンジニア力の低さがわかりましたw (用語がわからなかった…orz) ここは勉強しつつ拝見させていただきました! > MySQLのトランザクション分離(ISOLATION)レベルが、 > REPEATABLE READ(デフォルトがREPEATABLE READ)では、 > ファントムリード回避のためにネクストキーロックによる > インデックス挿入時のロックが発生する可能性があります。 つまるところ、「トランザクションが同時に複数かかった場合、後に来たほうをどうするか」の設定(トランザクション分離レベル)によって、 書き込んだデータを逐次見に行ってしまうので、見るタイミングで取得されるデータが違ってくる事がある(ファントムリロード)。 ってことですかね? この辺、デフォルトからいじっていないので「REPEATABLE READ」となっているはずなので、 ファントムリロードが発生する可能性があるということですね… なので、実コードではあまりバルクインサートは使わないほうが良さげ、という結論でいでしょうか?
sazi

2019/01/03 14:00 編集

MySQLはREADの高速性が得意分野なので、照会系を優先してデフォルトがREPEATABLE READなのだと思います。 REPEATABLE READならバルクインサートは使わないほうが良いと言っても、例えば、更新は夜間に纏めて行って、オンラインは照会が殆どで、競合自体が起きない作りなら、バルクインサートでも問題ないでしょうけど、オンラインで更新がそこそこあるなら、競合は発生するので使わない方が良いという事になります。 ISOLATIONレベルはシステムの特性に合せて設定するものですから、デフォルトのままだからバルクインサートを使わない方が良いというものでは無いと思いますよ。
nnahito

2019/01/06 02:40

おおーー!! 分かりやすいご返信ありがとうございます! MySQLのREPEATABLE READのような設定も全然知らなかったので、 とても勉強になりました! ありがとうございます!!
guest

0

単純なテーブルロックの話ではなく、デッドロックについてだと思います。
(バルクインサート デッドロックで検索すると、具体的な説明があると思います)

また、実処理(実サービス)上でInsertを発行する場合、基本的にトランザクション管理下で作業をすることになると思いますが、どういったエラーが発生した際にどこまでデータを反映するか、といったことは、とても関心の高い機能設計になると思います。
例えば、禁則文字が1レコード(の1カラム)だけ入っていたせいで、その他のレコードまですべてなかったことにするのか、それともエラーのあったレコードだけ登録するか、等。

例えばECサイトで複数の商品の入ったカートを購入遷移に移そうとするとき、1つの商品が在庫切れだからと「購入できません」となるとまずいので、在庫のある商品だけを購入遷移に流す、など。(普通はUI含めて回避する話ではありますが、いい例が思いつかなかったので。)

なので、どうしても使いたい理由がなければ使わない方がいいです。
そしてどうしても使いたい理由が私には思いつきません。

投稿2018/12/27 02:46

kunai

総合スコア5405

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sazi

2018/12/27 03:02

> どうしても使いたい理由が私には思いつきません。 SQLの発行回数が減ることで高速になります。
kunai

2018/12/27 03:05

サービス上で執り行われるInsertが、千件万件といったまとまりで行われるとは考えにくいので、どうしても使いたい理由にはなりにくいんじゃないかと。(数十件程度なら誤差レベルでは)
sazi

2018/12/27 04:07

少ない件数しか扱わない時に、敢えてbulk insertを使う必要性って事ですね。 成程。
nnahito

2019/01/03 12:56

ご回答有り難うございます!! > 単純なテーブルロックの話ではなく、デッドロックについてだと思います。 これだー!! デッドロック!ありがとうございます!!かなりスッキリしました>< 何かで聞いた記憶はあるものの、あまり理解せずに終わっていまい、いざ知識が必要な時にソースを提示できず、 すごくもやもやしておりました。。。 sazi様とkunai様のやり取りを見、 「件数が少ないときにはバルクインサートは利用しないほうがいい」という理由がわかりました。 ありがとうございます!
guest

0

バルクインサートはDBロックが掛かるので、実コードでは使わない方が良い

インサートについては更新・削除よりも他の作業に対して影響がでにくいので
あまり気にしなくてよいでしょう。
バルクインサートが原因のDBロック(テーブルロック?)もないと思います

もちろんトランザクションにおいてrollbackする可能があるならあまり大量のデータを
やり取りするのは効率的ではないかもしれません

1データ毎の流し込みをすると1アクション毎にセッションの接続・開放が発生し
オーバーヘッドが大きいです。
大量データについては基本的にバルクインサートするのが妥当でしょう。
(適正な単位があるので環境によっては分割が必要)

投稿2018/12/27 02:34

yambejp

総合スコア116468

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nnahito

2019/01/03 12:53

ご回答有り難うございます! なるほど、DBロックは発生しないのですね… 勘違いしておりました。 > 大量データについては基本的にバルクインサートするのが妥当 こちらありがとうございます!
guest

0

実コードとはいってもあくまでDBにSQL文を届けるだけなので関係ないと思います。
要はPHPの処理を「formタグから送るか」、「Ajaxから実行するか」の違いと似たようなものかと。
フレームワークでバルクインサート用のTraitを作った という例もあるようですし。
処理時間が長くなったり、1つ1つ実行しているということはinsert文の数だけDBアクセスが発生していて
WebサーバーにもDBサーバーにも負荷がかかるのでそちらの方が問題としては大きいです。

投稿2018/12/27 02:22

編集2018/12/27 02:24
m.ts10806

総合スコア80875

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nnahito

2018/12/27 02:31

ご回答有り難うございます! > 処理時間が長くなったり、1つ1つ実行しているということはinsert文の数だけDBアクセスが発生していて WebサーバーにもDBサーバーにも負荷がかかるのでそちらの方が問題としては大きい なるほど、完全に記憶違いでしたね。 ありがとうございます。 ちなみにバルクインサートは何件くらいのinsertから採用するのが適切なのでしょうか?
m.ts10806

2018/12/27 02:36

んー。 件数ではないと思います。 極端に言えば、1カラムしかないテーブルと100カラムあるテーブルでは1レコード挿入時の負荷が違いますし、テーブル構成にもよります。どれくらいのサイズのデータが入るとか。 タイムアウトしてしまうようになったときやサーバー側で負荷増大を感知した際に、改善策のひとつとして挙げるくらいでしょうか。 他の回答者の意見も待って参考にしてみてください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問