おすすめ記事

ファンクションインデックス

ファンクションインデックス
CREATE OR REPLACE PACKAGE TEST_PKG AS
/* ファンクションインデックス
* テスト作成
*/ -- TEST_FUNC 用のオブジェクトタイプを作成
TYPE TEST_FUNC_ROW IS RECORD
(
ID NUMBER -- 主キーです
, NAME VARCHAR2(40) -- 名前
, Bdate DATE -- 誕生日
, ADDRESS VARCHAR2(255) -- 住所
); -- TEST_FUNC 用のレコードセットを定義
TYPE TEST_FUNC_RSET IS TABLE OF TEST_FUNC_ROW; /* ■□■□ TEST_FUNC
* テスト
* 得意先を検索する
*/
FUNCTION TEST_FUNC
(
PARM1 IN NUMBER -- 1つ目のパラメータ
, PARM2 IN VARCHAR2 -- 2つ目のパラメータ
)
RETURN TEST_FUNC_RSET PIPELINED; END;
/ CREATE OR REPLACE PACKAGE BODY TEST_PKG AS
/*
* テスト作成 ファンクションインデックス
*/ /* ■□■□ TEST_FUNC
* テスト
* 得意先を検索する
*/
FUNCTION TEST_FUNC
(
PARM1 IN NUMBER -- 1つ目のパラメータ
, PARM2 IN VARCHAR2 -- 2つ目のパラメータ
)
RETURN TEST_FUNC_RSET PIPELINED
IS CURSOR Cur_Main ファンクションインデックス IS
-- 本番時は以下のSQLを修正し、
-- このコメントを削除する。
SELECT * -- 解説のために * ね
FROM xTEST_FUNC_VIEW
WHERE
1 = 1
AND /> AND NAME LIKE PARM2
; Row_Main Cur_Main%ROWTYPE; ReturnRow TEST_FUNC_ROW; BEGIN OPEN Cur_Main;
Loop
FETCH Cur_Main INTO Row_Main;
EXIT WHEN Cur_Main%NOTFOUND; ReturnRow.ID := Row_Main.ID; -- 主キーです
ReturnRow.NAME := Row_Main.NAME; -- 名前
ReturnRow.Bdate := Row_Main.Bdate; -- 誕生日
ReturnRow.ADDRESS := Row_Main.ADDRESS;-- 住所 PIPE ROW(ReturnRow); -- データを出力する。 END Loop; RETURN; END TEST_FUNC; END;
/

SQL ServerとOracleの一番大きな違い

単純なロジックはOracleの方が書きやすい。SQL ServerのIfなどのステートメントブロックにBEGIN ~ END って書かないといけないのは、大概勘弁して欲しいと思います。それでも、わたしがSQL Serverを推しているのは、SELECT系のストアドプログラムが圧倒的に書きやすいから。逆にOracleはSELECT系のストアドプログラムが書きにくく、Oracleが圧倒的なシェアを持っていたころに経験したSEたちに、「ストアドプログラムはバッチのためにある」という誤解を持たせてしまっています。

  1. ワークテーブルを使う
    セッションIDをキーにしたり、夜間バッチで消したりと余計なコストが掛かる
  2. REF CURSOR データ型の引数に戻す
    フレームワークが対応していなかったりするし、テストが簡単にはできない
  3. PL/SQL表を使う
    わたしはこのパターンを推奨

■ Oracleの場合

CREATE OR REPLACE PACKAGE TEST_PKG AS
/*
* テスト作成
*/

-- TEST_FUNC 用のオブジェクトタイプを作成
TYPE TEST_FUNC_ROW IS RECORD
(
ID NUMBER -- 主キーです
, NAME VARCHAR2(40) -- 名前
, Bdate DATE -- ファンクションインデックス ファンクションインデックス 誕生日
, ADDRESS VARCHAR2(255) -- 住所
);

-- TEST_FUNC 用のレコードセットを定義
TYPE TEST_FUNC_RSET IS TABLE OF TEST_FUNC_ROW;

/* ■□■□ TEST_FUNC
* テスト
* 得意先を検索する
*/
FUNCTION TEST_FUNC
(
PARM1 IN NUMBER -- 1つ目のパラメータ
, PARM2 IN VARCHAR2 -- 2つ目のパラメータ
)
RETURN TEST_FUNC_RSET PIPELINED;

END;
/

CREATE OR REPLACE PACKAGE BODY TEST_PKG AS
/*
* テスト作成
*/

/* ■□■□ TEST_FUNC
* テスト
* 得意先を検索する
*/
FUNCTION TEST_FUNC
(
PARM1 IN NUMBER -- 1つ目のパラメータ
, PARM2 IN VARCHAR2 -- 2つ目のパラメータ
)
RETURN TEST_FUNC_RSET PIPELINED
IS

CURSOR Cur_Main IS
-- 本番時は以下のSQLを修正し、
-- このコメントを削除する。
SELECT * -- 解説のために * ね
FROM xTEST_FUNC_VIEW
WHERE
1 = 1
AND /> AND NAME LIKE PARM2
;

Row_Main Cur_Main%ROWTYPE;

ReturnRow TEST_FUNC_ROW;

ファンクションインデックス ファンクションインデックス

BEGIN

OPEN Cur_Main;
Loop
FETCH Cur_Main INTO Row_Main;
EXIT WHEN Cur_Main%NOTFOUND;

ReturnRow.ID := Row_Main.ID; -- 主キーです
ReturnRow.NAME := Row_Main.NAME; -- 名前
ReturnRow.Bdate := Row_Main.ファンクションインデックス Bdate; -- 誕生日
ReturnRow.ADDRESS := Row_Main.ADDRESS;-- 住所

PIPE ROW(ReturnRow); -- データを出力する。

END Loop;

RETURN;

ファンクションインデックス

END TEST_FUNC;

END;
/

■ SQL Serverの場合

/*
* テスト作成
*/

IF EXISTS
(SELECT * FROM sys.objects
WHERE object_id = OBJECT_ID(N'[dbo].[TEST_FUNC]')
AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].ファンクションインデックス [TEST_FUNC]
GO

/* ■□■□ TEST_FUNC
* テスト
*/
CREATE PROCEDURE TEST_FUNC
(
@PARM1 INT -- 1つ目のパラメータ
, @PARM2 VARCHAR(40) -- 2つ目のパラメータ
)
AS

SET NOCOUNT ON;

-- 本番時は以下のSQLを修正し、
-- このコメントを削除する。
SELECT * -- 解説のために * ね
FROM xTEST_FUNC_VIEW
WHERE
1 = 1
AND /> AND NAME LIKE @PARM2
;

GO

ファンクションインデックス

WHERE句の左辺に算術演算や関数を指定すると,インデックスが使われません。例えば,
SELECT NAME FROM CUSTOMERS
WHERE SAL - TAX > 1000

とすると,たとえSALフィールドにインデックスが定義されていてもテーブル全体を走査してしまいます。こうした場合は,
SELECT NAME FROM CUSTOMERS
WHERE SAL > ファンクションインデックス TAX + 1000

インデックスが付加されているフィールドであっても,LIKE ‘%AAA’ のような「後方一致」を指定すると,インデックスを検索せずにデータ部の全表走査が行われます。したがって「後方一致」の使用はなるべく避けるようにしましょう。どうしても必要であるなら,

といった方法を検討して下さい。
●IS NULL,IS NOT NULLを単独で使わない

条件を表すWHERE句にIS NULL/IS NOT NULLを指定したときは,インデックスを定義したフィールドであっても,全表走査が行われます。したがって,これらの条件を指定するときは,単独で指定するのではなく,何らかのかなり絞り込める条件を合わせて指定してください。例えば,問い合わせの結果を変更せずに「B = 10」の条件を付加できるなら
…WHERE A IS NULL

とする代わりに
…WHERE A IS NULL AND B = 10

SELECT文にDISTINCT*Aを指定すると処理に非常に時間がかかります。DISTINCTを使用するのは極力避けましょう。DISTINCTと同等の結果を得ることのできるSQL文にEXISTSがあります。例えば,
SELECT DISTINCT a.ID1, ファンクションインデックス a.NAME1 FROM
TABLE1 a, TABLE2 b WHERE a.ID1 = b.ID2

のSQL文は,副問い合わせの条件としてEXISTSを指定して
SELECT a.ID1, a.NAME1 FROM TABLE1 a
WHERE EXISTS ( SELECT ‘X’ FROM
TABLE2 b WHERE ファンクションインデックス a.ID1 = b.ID2)

と書き換えることができます。同様に,NOT INからNOT EXISTSに代替することによってパフォーマンスが向上することもあるので,これも検討してみてください。
●GROUP BY,ORDER BY,HAVINGは注意する

GROUP BY句,ORDER BY句,HAVING句は,余分なディスク入出力が発生したりディスク領域を使うので,自分もしくはほかのプログラムのパフォーマンスに悪影響を及ぼします。このことを念頭において,使わずに済むならなるべく使わないようにしましょう。
●演算子の組み合わせで速度が変わる

検索条件に,「>」「<」「=」をANDで組み合わせるときは,指定の仕方によってインデックスの使われ方が異なります。等号と不等号の組み合わせは,等号のみインデックスが使われます。例えば,
SELECT NAME FROM CUSTOMERS
WHERE JOB = ‘MANAGER’
AND SAL > 1000

とすると,「JOB = ‘MANAGER’」にはインデックスが使われますが,「SAL > 1000」には使われません。また,不等号同士の組み合わせでは,先に指定した条件だけにインデックスが使われます。つまり
SELECT NAME FROM CUSTOMERS
WHERE TAX > 100
AND SAL > 1000

のSQL文では,RDBMSは「TAX > 100」だけにインデックスを使い「SAL > 1000」には使いません。
●テーブルの別名を利用する

テーブルに別名をつけて,フィールド名にはその別名をつけると,SQL文の解析処理を減らすことができます。例えば,
SELECT ID, NAME FROM CUSTOMERS
WHERE SAL < 1000
よりも,
SELECT a.ID, a.NAME FROM CUSTOMERS a
WHERE SAL < 1000
のほうが高速になります。
●SQL文の表現を統一する

基板検査に役立つ治具とは?おすすめのメーカー5選つき

マニュアルの表紙で、タイトルが「装置導入の必読マニュアル」と書かれている

【特徴】
テストデータシステム社は、ICやLSIといった半導体製品の加工、検査、バックグラインドと実装基板のテストプラグラム設計・開発、テスト機器の製造・販売を進めてきています。特に、いろいろな製品の実装基板検査の実績とノウハウは、ソフト面・ハード面から検討を加えることができ、最大のコストパフォーマンスを引き出す検査・運用方法を提案できることが強みです。これらの技術と経験を踏まえて、製品品質の向上とユーザーの信頼に応えてきたことが、会社を成長させ続けています。

③ 芙蓉電機株式会社

不要電機の基板検査治具

【所在地】
埼玉県坂戸市浅羽野一丁目一番地九号

【営業品目】
フィクスチャー・プリント基板ASSYチェッカー・エージング装置・各種位置決め治具・各種メカニズム検査用チェッカー各種ME機器設計製作

【特徴】
芙蓉電機の特徴を箇条書きで表してみましょう。

  • 35年以上の検査治具の製作経験による功績は、接触不良トラブルの大幅な削減です。
  • 設計者が設計から製作まで担当することで、高精度の検査治具の製作が可能です。
  • レーザー加工機によって、複雑で繊細な加工が可能です。
  • 設計から製作まで社内一貫で行うことで、低コストで製作が可能としています。

【実績】
芙蓉電機が製作した検査治具の実績のうち、2016年の実績を示します。
A社 38機種、B社 81機種、E社 9機種、F社 47機種、G社 4機種、H社 39機種、I社 9機種、J社 5機種

④ 株式会社アイ・エム・アイ(IMI)

IMIプリント基板検査治具

【所在地】
長野県茅野市湖東7062-3

【営業品目】
プリント基板検査治具製造、ファンクション・インサーキット治具製造、組み立て用治具製造、半導体・液晶製造装置用部品販売、PSCD検査治具製造

【特徴】
創業以来、人と人との繋がりと新しい技術への挑戦を大切に考えて業務に当たってきた結果、「この製品はIMIでなければ頼めない」とユーザーから言われるまでに、会社の信頼感が増しています。

  1. 心地よい質感を追求した治具の設計。例えば、「手で触れる部分に丸みを持たせることでストレスをなくす」という治具の設計が、次回もIMIの製品を使いたいと、ユーザーに思わせることです。
  2. 常に新しいことへの挑戦。ユーザーが求めているものより、もっと良いものを提供したいという想いの現れです。
  3. 人の手の感覚を大切にすること。作業者が使いやすいものを提供するという「こだわり」です。

⑤ 株式会社トーク

トーク社インサーキットテスタ用治具

【所在地】
川崎本社:神奈川県川崎市高津区下作延2-36-51
伊那工場:長野県伊那市上牧7095-2

【営業品目】
各種ファンクションテスタ用治具設計・製作販売、各種インサーキットテスタ用治具設計・製作販売、治工具類全般、チップ抵抗測定治具製作販売、プリント基板設計・製作・実装、自動計測機器製作販売、ソフトウェアの製作販売、樹脂加工全般、板金加工全般

【特徴】
トーク社の強みは、「実績と経験」「社内一貫生産」「技術力を活かす社内設備」「協力工場連携による多様な対応」「どんなニーズでも対応する力」です。
「社内一貫生産」:社内技術者によって、治具製作における設計-加工-組立-動作確認を、一貫して生産することができています。
「協力工場連携による多様な対応」:幅広い分野の社外工場とユーザーとの間で築いてきた関係から、高密度の基板製作・精密金属加工・大型板金加工・高度なソフトウェア設計などを、連携して対応することが可能です。

【実績】
家電メーカー:カーオーディオ、AV機器、業務用機器、空調機器
アミューズメントメーカー:パチンコ、スロット、ゲーム周辺機器、アミューズメント機器
自動車メーカー・ 部品メーカー・ 産業機器メーカー

SQL実行計画の疑問解決には「とりあえずEXPLAIN」しよう

EXPLAIN は、SQLの実行計画に関する情報を取得するためのステートメントです。実行計画とは「どのインデックスを使って(あるいはインデックスを使わずにテーブルスキャンで)クエリーを処理するか」をMySQLが判断した結果のことです。「インデックスはちゃんと使われているだろうか」「インデックスでどこまでクエリーを効率的に処理できているだろうか」という疑問が湧いた時には、「とりあえず EXPLAIN で」となりますよね。

EXPLAIN のマニュアルはこちらに、 EXPLAIN の出力結果のカラムの意味についてはこちらに記載があります。

EXPLAINの何を見るか

このような場合は、「とりあえず EXPLAIN 」を見てみましょう。

EXPLAIN はMySQLのオプティマイザーがどの実行計画を選んだかを表示させるステートメントです。 possible_keys からは「MySQLはこのクエリーに対して some_index または another_index が使えると判断した」、 key と key_len からは「実際に使ったのは another_index で利用したのキー長さは34バイト」、 rows からは「実行計画上ではこのクエリーは9026812(約900万)行を検査する」、 Extra: Using index ファンクションインデックス からは「テーブルそのものからデータを読み取らず、インデックスだけから読み取るデータで完結する」といったことが EXPLAIN の出力結果から読み取れます。

しかし、 another_index が本当にこのクエリーにとって最良の選択なのかは EXPLAIN から読み取ることはできません。ひょっとしたら some_index の方が速い可能性は十分あります。あるいは possible_keys に表示されていない(MySQLが「利用できない」と判断した)インデックスの方が効率が良い可能性もないわけではありません(体感ではほぼないが実際にそのようなケースも存在する)。

また、実行計画上は約900万行を検査することになっていますが、「実際に何行検査したのか」は読み取れません。統計情報と実際のデータの分布に乖離がある場合、この値もまた乖離することになります。最後に、これは「 EXPLAIN を実行した時点で実行計画がこのように選択された」という情報であり、今後統計情報の変化により変更される可能性があります。

EXPLAINの結果を踏まえて確認すること

another_indexは本当に最適なインデックスなのか

泥臭い方法ですが、実際に実行してみるのが一番です。 USE INDEX および IGNORE INDEX 構文を使うことで、そのクエリーに利用するインデックスを指定できます。

USE INDEX は possible_keys の値を書き換える(上書きする)ためのキーワードです。インデックスはコンマ区切りで複数指定可能で「 USE INDEX で指定したインデックスの中から利用するインデックスを決定せよ」というような意味合いになります(通常は指定するインデックスが1つで「このインデックスを利用してクエリーを処理せよ」という意味合いで利用するキーワード)。

IGNORE INDEX はその逆で、MySQLが選んだ possible_keys から特定のインデックスを除外します。「 possible_keys の選定はMySQLに任せるが、 IGNORE INDEX で指定したインデックスは利用してはいけない」というような意味合いになります(よってテーブル上の全てのインデックスを IGNORE INDEX に指定すると強制的にテーブルスキャンにできる)。 possible_keys が3つ以上ある場合で、MySQLが次にどのインデックスを選ぼうとするのかを知りたい時などに利用できます。

上記の例では ファンクションインデックス ファンクションインデックス USE INDEX(some_index) で some_index を選ばせた場合に1割程度遅くなったということで、「MySQLの選んだ another_index は正しかった」ということが判りました。実際に実行して試してみる場合、(元のクエリーも試してみるクエリーも)必ずクエリーを複数回実行することを忘れないでください。

クエリーは本当に900万行も検査しているのか

そのクエリーがどれだけ行を読み込んだのかは Handler_% ステータス変数で確認できます。ステータス変数は SHOW STATUS ステートメントで参照できるMySQL内部のステータスです(多くはカウンター)。ステータス変数の多くは「セッションスコープ(接続中のスレッドのみのステータス変数)」と「グローバルスコープ(MySQLの起動から現在まで全てのステータス変数の累計)」があり、それぞれ SHOW SESSION STATUS , SHOW GLOBAL STATUS ステートメントで表示できます( SESSION または GLOBAL キーワードを省略した場合はセッションスコープの値が出力される)。

ステータス変数には多くの種類がありますが、ここでは Handler_ で始まるステータス変数を確認しましょう。

FLUSH STATUS は「セッションスコープのステータス変数をクリアする(クリアされないものもある)」ステートメントです。まれに「グローバルスコープでステータス変数をクリアする」と誤解されているケースがありますが、セッションスコープ限定です。余計な値が混じらないように SHOW SESSION STATUS の前に実行してみました。各ステータス変数の詳細はリファレンスマニュアルに説明を譲りますが、ここからはインデックスを利用した行の読み取りを意味する Handler_read_next がおよそ48万回コールされていることが分かります。統計情報をもとにオプティマイザーが「行の検査が必要」と判断した行数は90万行なので、見積もりと実際の間には40万行の乖離があったことになります。

このような事態はなぜ発生するのでしょうか。端的には統計情報が「サンプリング値」をもとに作成されることが原因です。オプティマイザーは統計情報をもとに実行計画を計算しますので、入力値となる統計情報(=サンプリング値)が間違っている(実際のデータの分布と著しく乖離している)場合、出力である実行計画もまた間違っているものとなる可能性があります。「統計情報が間違っている」といえば ANALYZE TABLE ステートメントです。とりあえず実行してみましょう。

  1. InnoDBはデフォルトの設定で「前回の統計情報の更新から累計してテーブル全体の10%以上(MySQL 5.5とそれ以前は6.ファンクションインデックス 25%)が更新された場合、バックグラウンド(非同期)で統計情報を再作成する」ようになっている
  2. InnoDBのサンプリングの設定はMySQL 5.5とそれ以前では1インデックスあたり8ページ(ハードコード)、MySQL 5.6では1インデックスあたり20ページ(設定可能)。InnoDBページのデフォルトは16KBなので1つのインデックスのサイズが数十GB、100GBを超えたとしてもデフォルトのままでは128KB~320KB程度しかサンプルを取らない。これはインデックスのサイズがせいぜい数MBであれば十分な精度だが、サイズが大きくなるに従って精度が悪く(=統計情報が間違いやすく)なる。

まず 1. の通り、トラフィックの流れている環境であればバックグラウンドで統計情報の再作成が頻繁に行われているため、強制的に統計情報を再作成する ANALYZE TABLE を実行しても大きな変化はなかったと考えられます。閾値にギリギリで届かないような更新量でない限りは ANALYZE TABLE の実行によって大きく実行計画が変わることはまれです(ただしInnoDBに限る。MyISAMの場合はバックグラウンドで統計情報を再作成する機能は存在しないため、 ANALYZE TABLE を実行するまで統計情報は古いまま)。

そして 2. の通り、インデックスのサイズが大きくなれば大きくなるほどInnoDBの統計情報の誤差は大きくなります。MySQL 5.6とそれ以降では、1インデックスあたりのサンプリングページ数をinnodb_stats_persistent_sample_pagesオプションで指定、または CREATE TABLE や ALTER TABLE でテーブルごとに指定できるようになったためこれを大きくすることも手ですが、サンプリングのページ数が増えれば統計情報の再作成処理も重くなりますので、最適な値を見つける必要があるでしょう。

Handler_% ステータス変数と EXPLAIN の rows が大きく乖離している場合、「ベースとなる統計情報が間違っているためオプティマイザーが導き出した実行計画もまた間違っている」可能性があることを考慮してください(ただし、オプティマイザーの精度が上がっても同じインデックスを利用している限りクエリーそのものの速度は向上しないことに注意)。

そのExtraは本当に望ましいのか

EXPLAIN の見方を説明している時によく聞かれる質問として「 Extra に"Using index"(ほかにも"Using intersect"や"Using temporary"など)が出ていますがこれは直した方が良いですか?」というものがあります。正直これはケースバイケースで、全てのケースを説明するわけにはいきません。まずはマニュアルのEXPLAINの追加情報を参照してください。意味的なものはここにほぼ網羅されています。 Extra 列の出力しうる表示はたくさんありますが、ここでは比較的よく目にする3つに絞って説明したいと思います。

Using filesort

MySQLのソートは(filesortと出力されているが、必ずしもテンポラリーファイルを使用するとは限らない)クイックソートです。クイックソートの平均計算時間が示す通り、ソート処理はソート対象の行が多くなれば多くなるほど(線形以上に)遅くなっていきます。また、インデックスを利用したソートの無効化(インデックスが既にソート済みの状態で並べられているため、追加のソートが必要ない状態)は LIMIT 句での最適化が効きますが、クイックソートが実行される場合にはこの最適化が効きません。 WHERE 句で絞り込んだ結果が十分小さい場合はこれが出力されても特に問題にはならないでしょう。絞り込んだ結果がどんどん大きくなる(例えばユーザーコンテンツなどは時間経過とともにどんどん増えていくのが常)場合は注意が必要です。

Using index

  1. インデックス上から条件にマッチするリーフを探す
  2. インデックスのリーフ上に書かれた情報から行の位置を探す
  3. 行をフェッチする

Using indexが示すのはインデックス上に書かれた情報だけで(インデックスは「ソート済みのデータの複製(サブセット)」でありインデックスを作成したカラムの値を含む)、要求された情報の取り出しが終了したため 2. と 3. のステップを省略した、というものです。大概の場合悪い意味ではありませんが、「100バイトのインデックスを100リーフ読んでUsing index」と「4バイトのインデックスを10リーフ読んで各10バイトの行を10行フェッチ」というケースもあります(さすがにここまで極端な例はないと思うが、必ずしも最良を表すものではないということで)。

Using temporary

"Using temporary"はソートのために暗黙の( CREATE TEMPORARY TABLE ステートメントで作成するテンポラリーテーブルに対して「暗黙の」としている)テンポラリーテーブルを利用していることを示します。単にインデックスがないカラムでソート、インデックスがあっても関数や演算子を利用した結果でのソートはクイックソートで済みますが、集計関数を利用した結果でのソートは暗黙のテンポラリーテーブルが必要になります(テンポラリーテーブルを作成した後にクイックソート)。

また、MySQLでは昇順(ASC)と降順(DESC)が混じったソートは暗黙のテンポラリーテーブルを使用することも有名です。暗黙のテンポラリーテーブルは一定のサイズ( max_heap_table_size , tmp_table_sizez のいずれか小さい方)を超えるとMyISAM(5.7ではデフォルトでInnoDB)としてストレージ上に固定化されるため、ソート以上に WHERE 句での絞り込み後の結果サイズによって性能が劣化します。

EXPLAINの変更点

EXPLAIN はずっと昔からあり利用用途も変わっていませんが、MySQL 5.6と5.7でそれぞれ少しずつ機能が追加がされています。

MySQL 5.6での変更

  • DELETE , INSERT , REPLACE , UPDATE ステートメントが EXPLAIN できるようになった。5.5とそれ以前のバージョンでは SELECT のみ EXPLAIN にかけることができた。
  • EXPLAIN format=json .. がサポートされた。 format=json キーワードを指定すると出力が少し増えたものがJSON形式で返ってくるようになる。また EXTENDED ファンクションインデックス キーワードを指定した時と同じように最適化後のSQLをワーニングバッファに格納する。

MySQL 5.7での変更

  • EXTENDED キーワードと PARTITIONS キーワードがデフォルトで指定された状態になった。MySQL 5.6とそれ以前ではこれらは同時に指定できなかった。
  • EXPLAIN FOR CONNECTION n 構文がサポートされた。 "n" に SHOW PROCESSLIST で出力される "Id" を指定することで、現在実行中のステートメントを(コピー&ペーストすることなく) EXPLAIN できる。

EXPLAIN はSQLの実行計画に関する情報を取得するためのステートメントです。 EXPLAIN の結果は「その時点で実行計画がこのように選択された」という情報であり、統計情報の変化により変更される可能性があります。InnoDBの統計情報はサンプリングのため、テーブルが大きくなると統計情報と実際の値の分布が異なってくる傾向があります。利用されているインデックスが最適なものかどうかは、 USE INDEX , IGNORE INDEX 句を利用して実際に比べてみるのが一番です。

一概には言えませんが、"Using filesort", "Using temporary"は WHERE 句で絞り込んだ後の結果セットが大きくなるほど遅くなっていくので注意しましょう。

Yuki's bnb blog

こんにちは!Yukiといいます。本業のかたわら大阪で2016年夏から民泊運営のお手伝いをしています。民泊業務に関する様々なことを自動化・効率化したいと思い日々活動しています。 お気軽にコメント・お問い合わせください :) TOEICスコア 985

【保存版!】Googleフォームの質問と回答をGASで自在に取り出す方法まとめ

google form app script

今回は Googleフォームの回答をGoogle Apps Script (GAS) ファンクションインデックス を使って自在に取り出す方法 を紹介します。

簡単!Googleフォームの質問と回答をGASで取得しよう

変数itemResponsesにフォーム内のすべての質問と回答を格納する

google form get responses

回答者がGoogleフォームから提出した内容は e として、関数 submitForm に渡されます。

この e にはGoogleフォームの回答者が提出した様々な内容が詰まっています。回答済みアンケート用紙が入った封筒のようなものです。

封筒の外からでは中身が見えませんので封筒を開けてアンケート用紙を取り出す必要があります。それを行っているのが var itemResponses = e.response.getItemResponses(); の部分です。

google apps script form get responses

  • 〇番目の質問内容を知りたい
  • 〇番目の質問の種類は記述式か選択式か知りたい
  • 〇番目の回答を知りたい


個々の質問と回答を取得する第一歩は 何番目の質問と回答の束かを指定する ことです。

変数itemResponses内の質問&回答の束を指定する

google form index number array

このように itemResponses[インデックス番号] と記述すると個別の質問と回答の束を指定することができます。

インデックス番号は0から始まるため、ひとつ目の質問と回答の束を指定したい場合、 itemResponses[0] と記述します。

指定した束から質問や回答などの情報を取り出す

google form item responses

インデックス番号

今回のサンプルでは itemResponses[0] と指定したのでわざわざインデックス番号を取得しなくても結果はわかりますが、ループで複数の束を処理したり、何番目の質問かを確認、出力したりしたい時に役立ちます。

関連記事

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次
閉じる