メモってこ!

IT関連系のあれやこれ

DataTableのデータを更新する

  •  書いたきっかけ
  • 使い方
  • そのほか

 

■書いたきっかけ

一括updateが一括insertのようにスマートにできず、

パフォーマンス改善に悩んで使用した。

この処理とSQL処理時にstruct型を使用することが要。

一括で取得したデータをC#側でコード処理、既存データにupdateかけたかった。

ほかにもいろいろ方法はあったが、影響範囲が狭い(影響範囲が最小で完結する)DataTableを更新するというものを採用。

 

■使い方

 

csharp.programmer-reference.com

 

■そのほか

bulkinsertのようにbulkupdateSQLの書き方があるが、updateのデータ変更部分でCASEを使用した条件分岐をするだけで、不細工。

パフォーマンスにも不安。

 

データインポートバッチのパフォーマンス改善

  • 書いたきっかけ
  • 前提事項
  • やったこと
  • 調べたこと
  • そのほか

 

■書いたきっかけ

バッチ作成で痛い目を見たので備忘録。

VB.NETでなくC#で作ったのが悪いのか。。

VB.NETで動いていたパフォーマンスをなぜか発揮できない。paizaのスキルチェックの感じ、多分C#にも原因がある)

 

■パフォ-マンス改善

ネックはやはり大量データ取り込み処理時。

一度DBか取り込んだ後は楽(ここは案件のDB性能のおかげ)。

 

■前提事項

環境(DB性能、メモリなど)は優秀。一度のバッチ実行で数万件の取り込み・出力が問題なくできる想定の環境。

逆に数十万件以降は、想定されていない。

物理テーブルのワークテーブル経由であれば、数十万とはいかずに百何万もクラッシュせずに処理に耐えれるスペックではあったが(DataTableは場合によってはクラッシュする)、バッチのパフォーマンスが追い付かず時間がとてもかかる(といっても一晩かかるレベルではない)。

バッチの大まかな動きは以下↓

ファイル読み込み→文字列チェック

→ワークテーブルへ一時取り込み(Microsoftルールで決まっている複数Insert件数上限値が1000件のため1000件ずつくりかえし発行)

→データ加工→データ登録

 

■やったこと

色々調べて採用したもの

 

SQL文生成時は文字列からStringBuilder採用に

stringにSQL文を入れて、SQL発行するのをやめることに。

見やすいけど、数ミリ秒改善(塵積で、劇的改善)

×sql = "SELECT * FROM XXXX";
〇StringBuilder str = new StringBuilder();
str.Append("SELECT * FROM XXXX");

 

〇INSERT文は一括で

すでに採用済み。

INSERT INTO XXXX(id, name, age) 
VALUES(1, 'hanako', 21, ' okinawa')(2, 'tarou', 23)
(3, 'kenta', 25)...

 

〇List型宣言時、あらかじめ枠の確保をする

効果は実感できてないが、簡単だったので追記。

var a = new List<int>(1000);

 

〇データ保持にList型ではなく、配列の使用

調べた記事によっては意見が分かれるが、今回はパフォーマンス改善の実感あり。

 

〇コミットはまとめて1回

バッチ処理が途中で終了する可能性を考慮し、

トランザクションを要所要所で張っていた。

負荷分散のため、SQL発行回数とコミット回数、それぞれ変更可能としていたが、

最低限の1回にしたほうがトータル的にパフォーマンスが良かった。

(調べた記事では件数によって、パフォーマンスが変わる、一定件数ではパフォーマンスに変化なしとの検証結果だったので、環境要因が大きいかもしれない)

 

■調べたこと

 

enumを使用しない

取り込み項目の可視化のため、enumを採用していた。

このenumをint変換する処理が、理論的にはコストがかかる想定だったが

enumをintに変換するので、あらかじめintで書いたほうが良いという考え。

調べると検証記事あり)、パフォ-マンスに影響なし。

 

〇多重ループの並列化

概要はよかったが、並列化なので使いこなせず。

 

以下は、調べた記事↓

docs.sakai-sc.co.jp

 

kagamihoge.hatenablog.com

 

www.fujitsu.com

 

www.fenet.jp

 

qiita.com

 

qiita.com

 

■そのほか

・DB設計は大事

→PK,インデックス考える

 

・列ストアインデックス

→データ読み込みが改善するらしいが、データを取り込むバッチの前には

パフォーマンスの敵

DBのタイムアウト設定値

 

■書いたきっかけ

クエリ発行タイムアウト設定値の関係で、くそ重クエリが途中キャンセルなったので設定値延ばしたら問題になった件。

内結で指摘されたからよかったものの、WEBサービスでテーブルロック待機2時間待てる状態とかヤバイ。

※本記事はSQLServer。接続文字列でなく、xmlファイルに記述

 

■使用しているタイムアウト

〇プロパティ設定値

設定値の単位は

・接続タイムアウト

 →DB接続できない判定はこっち

<property name="ConnectTimeout"        value="60" />

・クエリ発行タイムアウト

<property name="CommandTimeout"        value="60" />

 

〇オプション設定値

設定値の単位はミリ秒

・ロックテーブルタイムアウト ← 今回新規追加

 →これを設定しないでロックテーブルへのクエリ実行を行った場合、クエリ発行タイムアウトが切れるまで延々と待機する

<option name="LOCK_TIMEOUT"                value="60000" />

 

■そのほか

参考サイト

 

〇ロックテーブル再現

maitakeramen.hatenablog.com

 

〇リファレンス

maitakeramen.hatenablog.com

 

 

開発時の簡易データバックアップ

  • 書いたきっかけ
  • テーブル作成

 

■書いたきっかけ

いつも書き方を忘れる。

開発時、DELETEや大規模UPDATEする前に一時テーブル作ってデータ退避させよう。

トランザクションはってから実行とか、保険をかける方法はいくらでもあるけど、今の自分にはこれが最適。前まで表作成→SELECT~INSERTしてた)

 

■テーブル作成

SQLServer

www.projectgroup.info

https://www.projectgroup.info/tips/SQLServer/SQL/SQL000025.html

 

Tweepy(TwitterAPI V2.0)の利用方法について

  • 書いたきっかけ
  • Tweepy(TwitterAPI v2)とは

  • 前提事項
  • 使い方
  • コード例
  • そのほか

 

■書いたきっかけ

とあるポイ活系サイト巡回中に懸賞botの作成記事があり、自動化で懸賞bot作れるのであればぜひやりたいというのがきっかけ(2022/11~)。

ただ現時点での開始だとTwitterAPIは2.0に指定されており、2.0の記事にあまり出会えなくてドツボにはまったことによる。

※2月上旬にAPI有料化のお知らせが出たときは焦った

 

■Tweepy(TwitterAPI v2)とは

Twitterが提供しているAPIの一種。Pythonライブラリ。

Tweepyで検索するとv1.0のほうが上位に来る。

現時点でtwitterの開発ポータル開設した人は、v2.0の使用に制限される。

 

※XXX.OAuthHandlerの記述があればv1.0

 

■前提事項

Twitterの開発ポータルを開いたのは2022/11あたり。

開発ポータルの権限はEssential。

python初心者。

つぶやき方法は検索したら出たので、本記事はbot作成時に使用した項目のみ記載。

 

■使い方

以下リファレンス。

tweepy.mkuriki.com

 

TwitterAPIv2.0では上記リファレンスに載ってないことは、TwitterAPIの一覧に載っている関数の使用ができない。

また、負担軽減の観点からか、v2.0では取得件数もだいぶ制限される。

利用したい関数を上記リファレンスから探し、関数を検索エンジンで検索して、開発ポータルのリファレンスに飛び、両方とも参照するのがおすすめ。

 

〇検索

検索メソッドは2種あるが、Client.search_all_tweets()関数は、Essentialでは使用できない。使用できるのは1種である。

Client.search_recent_tweets(query*user_auth=Falseend_timeexpansionsmax_resultsmedia_fieldsnext_tokenplace_fieldspoll_fieldssince_idstart_timetweet_fieldsuntil_iduser_fields)

引用:https://tweepy.mkuriki.com/client.html#tweepy.Client.search_recent_tweets

関数名の通り最近のツイートから検索する関数。

第一引数queryが必須で、他はoptional。json形式で返却されてくる。

queryには検索キーワードを入力する。

v1.0だと自分がツイート済みかどうかの引数があるそうだが、上にはなさそうである。

optional項目に指定してやることで、取得結果内容が増える。

例:ツイートしたアカウントのidを取得したい → 引数にexpansions  ='author_id'を指定する

 

pythonだと当然なのか、一部引数のリファレンスはままだと使用ができない。

引数として使用できないという場合はアンダースコアに変えてみるとよい。

例:tweet.fields → tweet_fields

 

developer.twitter.com

 

・第一引数:queryについて

検索の第一引数内容によって、検索したい内容を指定することが可能。

文字制限があるのがネックだが、結構自由に条件指定が可能。

 

developer.twitter.com

 

 

リツイート

Client.retweet(tweet_id)

引用:https://tweepy.mkuriki.com/client.html#tweepy.Client.retweet

 

ツイートごとに割り振られているID(ツイートID)を引数にリツイート実行を行う関数。search_recent_tweetsと組み合わせれば、取得してきた特定条件を含むツイートをリツイートする、といったことが可能。

 

■コード例

client = tweepy.Client(
        bearer_token = '*****', #bearer_tokenないとAPI情報の読み取りができない
        consumer_key = '****',
        consumer_secret = '*****',
        access_token = '1595303721772101632-J4UHewLEyaJ399no7MgZveS2rSCO1B',
        access_token_secret = '****'
        )
 
my_user_id = client.get_user(username = '@から始まるid(id抜き)')[0]['id']

 

 

■そのほか

API実行エラーが出る

→tweepyのバージョン古くないか

pythonインタプリタモードで実行してないか(>>が先頭につくのはインタプリタモード。cmdで開けば普通にpyファイルを実行するだけ)

デベロッパーアカウントの権限は大丈夫か(読み取りのみになってないか)

→権限外の関数を使用しようとしてないか