↑の続きの16~30です。
30 SQL Developer Tips in 30 Days, Day 16: Comparing In-Memory Results with Autotrace
まず、このTipsはversion 4.0.3以上にアップグレードしていることが前提条件です。詳細については後述します。
version 4.0.3の95%はバグフィックスです。
そのバグの一つに同僚のプロダクトマネージャーMaria Colganが報告したものがあります。もしかしたらTwiterで彼女のことをご存知かもしれません。
ともあれ、彼女は12.1.0.2の新機能であるIn-Memoryを布教するのにSQL Developerを使用しています。
数日も必要なく、その使用方法を、今すぐ、数秒後に、知ることができたとしたら、どう思いますか?
In-Memoryは本当にすごい機能です。とはいえ、恐らくはそれが動作しているところを見たいことでしょう。自動トレースと新しいオプティマイザヒントによって簡単に知ることが出来ます。
テーブル等をスキャンするSQL文にヒントを付加したり外したりできます。この条件下でSQLを実行して自動トレースを比較したとすると、以下のようになります。
手順のまとめとしては、
- 自動トレースでクエリを実行
- 結果をピン止め
- 自動トレースで二番目のクエリを実行
- 結果をピン止め
- 一番目の自動トレース結果パネル右クリック、'Compare…with 2'を選択
4.0.3より前のバージョンでもこの機能は使用できますが、比較機能がゼロレベルの統計を考慮しません。比較時にそれらを取り除くことで、自動トレースの比較はより使いやすくなります。
さらに、In-Memory機能について
Maria氏はOpen World 2014の週に多数のハンズオンラボを開催しています。もしこれに参加を望むのなら売り切れてしまう前に登録してスケジュール帳に予定を入れてしまいましょう!
(原文へのリンク)
30 SQL Developer Tips in 30 Days, Day 17: Using SSH Tunnels
あなたはデータベースに接続しようとしました、が……
- サーバに直接アクセスできない
- リスナーポートに接続できない
この場合は、別のネットワークを介してデータベース接続が可能な手段があれば良いワケです。
その手段はおおむねSSHトンネルと呼ばれています。
SSHはポート22に接続し、たいていのロックダウンサーバではおおむね開放されています。
SSH接続が出来ると、SQL*Netトラフィックを接続に送信し、トンネルの反対側ではデータベース接続を確立します。
以上は簡潔な説明に過ぎないのですが、そこはWikipedia先生にお任せします。なので、これを読んでいる人はもう既にSSHトンネルについて十分詳しい、ということにします。
SQL Developerでは、ツール外で設定するのではなく、ツール内で設定が可能です。
まずやることとしては……
Version 4.0.3にアップグレードする
……と、設定が可能になります。
それからauthenticationの詳細を入力します。
こうすると、回りくどいもののSSHで接続出来ます。VM上でポートフォワーディングを作成すると、ホスト上のポート22のトラフィックをLinux VMのポート22にフォワードします。そうすると、サーバがデータベースに接続します。
通常のOracle接続プロパティにサーバ名やIPアドレスを使用している場合、その接続情報はSSH接続するサーバの情報も加える必要があります。
現在と今後
現在のバージョンでは、トンネルは接続レベルで定義します。ただ、一つ以上の接続でトンネルの接続情報を共有したい場合もあるかと思います。
よって、今後のリリースでは、設定でトンネル定義が出来るようにして、接続を作成するときにそれを利用できるようにする予定です。
(原文へのリンク)
30 SQL Developer Tips in 30 Days, Day 18: NULLs
本日の投稿は無に飲まれました……*1私はOracle Open Worldに向けてのパワポ集中モードに入っていたところ、本日の投稿を忘れてしまった! 思い返すところTipsチャレンジの第一日目、予定では一ヶ月に5000回の腕立て伏せだった……でも、ちょっとつらすぎんよ……腕立て伏せはまだやってはいるけど、5000回はムリ。Philip!お許し下さい!
そいでは、気持ちを切り替えまして。本日の投稿に参りたく候。
データの欠如は時に痛みを伴うことがあります。SQLと数学の場合には論理ビットは忘れてもよいですが*2、レコードを参照する場合、空白文字とNULL文字を見分けるのは難しいものです。
なので、SQL Developerは見た目で判別出来るようにしています。
設定!
ところで、昨日のSSHトンネルのグレートな投稿のように、Tipsの投稿はどれも大した分量はありません。しかし、今日のnull判別機能は、私を頭痛から何度も救ってくれました。
(原文へのリンク)
30 SQL Developer Tips in 30 Days, Day 19: Quick and Clean Table Copies
"すばやくきれいに(Quick and clean)"、とは何のことでしょうか。
以下のクエリを見てください。
create table new_table as select * from old_table where 1=2;
これを私は"すばやくテキトー(quick and dirty)"と呼んでおり、思うにあなたはこのテクニックを何度も使ったことがあるでしょう。
しかし、私は、カラムコメント・インデックス・パーティションも同様に持っていきたいのです。上記のクエリ後にテーブルのパーティショニングをすることはほとんど不可能です。
では、どうすればよいのでしょうか?
もしSQL Developer v4.0.3をお持ちであれば、ただ単にテーブルを右クリックして、それから……
Use as a Template
この機能は、ダイアログに新規テーブル名を入力して必要があれば変更を加えて、既存のテーブル定義を新規作成するテーブルに持っていきます。
コメントをよこせ!(※なお本日は世界海賊口調日)*4です。)
お次はパーティションだ!
ちょっと待った、インデックス・制約・パーティション名が衝突しているぜ!
そうでもないです。生成されるDDLを見てみると、SQL Developerはその点に考慮済みでそれらの名前の後ろに1をつけます。もちろん必要に応じてcreate tableのダイアログで変更が可能です。
更に欲望が出てデータもコピーしたい場合、INSERT AS SELECT
や、SQL DeveloperのCartやエクスポートなどのデータロード機能を使います。
(原文へのリンク)
30 SQL Developer Tips in 30 Days, Day 20: See, Click, Goto Error Messages
頻繁に寄せられる質問に以下のようなものがあります。
原因は以下のどちらかです。
- 適切でないエディタを使用している。
- エラーが無い*6
SQL Developerはデータベース用にPL/SQL IDEを持っています。私たちは、デバッガ・コンパイルメッセージサポート・プロファイリング・ブックマークなど、"洒落た(fancy)" IDEの機能を欲していることは確定的に明らかです。
私たちはProcedure Editorとして上記の機能を提供しています。
新規のPL/SQLオブジェクト作成・接続ツリーから既存のPL/SQLオブジェクトを選択・Procedure Editorに関連付けされたファイルタイプ(pls, pks, pkb)を選択するとき、Procedure Editorを実行します。
SQL Worksheetをどうしても使用したいのなら、ワークシートを自由記述形式のスクラッチパッドと見なすことも出来、Oracleになんでも送信することが出来ます……が、エラーになることでしょう。エラーがどこかを調べないといけません。
ワークシートのスクリプトエラーをクリックできるようにしました、が……
version 4.0にこの機能を追加しましたが、SQL用であってPL/SQLではありません。実際に試してみるのが良いでしょう。
(原文へのリンク)
30 SQL Developer Tips in 30 Days, Day 21: Executing Multiple Statments to Multiple Data Grids
あなたはせっかちですか?*7
あるクエリを実行後に別のクエリを実行し、両方の結果をデータグリッドで表示したいですか?
データベースのカーソルがオープンのままにならないか心配ですか?
これらは重要な質問です。
とはいえ、"冒険心"があるなら、気軽に以下を試してみてください。
- 複数のクエリを選択する
- 実行
もしくは、以下のGIFを見てください。
もう一つのTipsに気付きましたか?
結果セットのグリッドをマウスオーバーすると、そのグリッドを作成するのに使用したクエリをコンテキストヒントに表示します。
"冒険心"について補足
実行結果のカーソルはクエリの結果をホールドします。カーソルはクライアントに"すべての"読み込み結果を送信するまで開いたままになります。クエリを実行して結果をすべてフェッチせずにデータグリッドのパネルを開いたままにするクセがあると、SQL Devleoper上では痛くもかゆくもありませんが、DBAはあなたが多くのサーバリソースを消費していることに対して食ってかかってくることでしょう。用が済んだグリッドはクローズするようにして下さい。
そうすれば、DBAに感謝されることでしょう。
(原文へのリンク)
30 SQL Developer Posts in 30 Days, Day 22: It’s All in the Font
私はSQL Developerでサポートされている昔ながらの実行計画と同様に、SQL_IDで実行計画のキャッシュを出す機能も好きですが、古い方法で実行計画を出したいときもあるでしょう。
新しい方法
古い方法
……とはいえ、これは、ちょっと読み辛いものがあります。
この場合には、固定幅フォントを設定します。
Tools – Preferences – Code Editor – Fonts
フォントはホントに重要
データ表示に問題がある場合、それはおおむねフォントが原因です。表示したい文字と文字コードをサポートしているフォントを設定してください。我々はUnicodeを採用しているので、SQL Developerの文字化けについてはあまり心配する必要はありません。
(原文へのリンク)
30 SQL Developer Posts in 30 Days, Day 23: Invalid Objects
フォーラムで質問があったことの中で、私がこのブログで書いたことが無いものとしては、SQL DeveloperにおけるOracleデータベースのinvalidなオブジェクトの扱いについて、があります。本日の投稿はその件についです。
ブラウジング
すべてのINVALDを表示する
レポートを実行します。
オプションでレポートをフィルターするためのスキーマがあり、デフォルトではデータベース全体を表示します。
スキーマ全体のINVALIDなオブジェクトを修正したい!
接続を右クリックします。
ALL OBJECTS
をfalse
に設定します。これにより、スキーマのINVALIDなオブジェクトのみ再コンパイルされます。
(原文へのリンク)
30 SQL Developer Tips in 30 Days, Day 24: Hiding Schemas That Don’t Own Anything
多くのアプリケーションがデータベースにユーザアカウントを作りますが、そのスキーマには何も無いことがあります。これらのアカウントはアプリケーション用のスキーマにクエリを発行する許可を持ちますが、テーブルやビューなどを作成するためには使用しません。
SQL Developer上でそうしたデータベースのツリーをブラウジングするとき、そうした"フェイク"ユーザを非表示にしたいかもしれません。
フィルターする
ディクショナリ統計が更新されていることを確認してください。オブジェクトカウント用の追加チェックは、多数のアカウントが存在する場合には高い負荷を与える場合があります。
なお、アカウント管理をする場合には、DBAパネルも使えることを覚えておくと良いです。
(原文へのリンク)
30 SQL Developer Posts in 30 Days, Day 25: Importing Partitioned Tables to a Data Model
Oracle SQL Developer Data Modelerでパーティションスキーマをモデリングする方法全般についての質問を良く受けます。私たちはデータのパーツとサブパーツ*8について様々な方法をサポートしていますが、今日は以下について書きたいと思います。
- モデルのどこにパーティションはあるのか
- パーティーション以外をインポートする方法
パーティションはどこにある?
データモデルのテーブルを参照するとき、通常の方法ではパーティションは参照できません。なぜでしょうか?
Oracle Partitioningは、テーブル・インデックス・索引構成表を小さい断片に分割し、異なるディスクストレージ層で、アクセス性能を向上するために細粒度でのコスト効率を管理を可能にします。製品ページ
上記の説明のキーフレーズのうち、モデリングに関連するものは、"ディスクストレージ層"です。関係モデルが定義するのはデータがどのように関連するのか、です。ディスク上の格納や物理的な編成をどうするのかは、物理モデルの役割です。
以下のGIFを見てみましょう。
パーティションのインポートはしなくてもいいです、大変結構
テーブルは数百~数千のパーティションで構成可能です。ある単一のテーブルをパーティション化するのは、数ダースのテーブル群によって単一のテーブルを使うような感じです。この情報をインポートすると長時間かかる場合があります。一日の終わりに、ディスク上での編成方法だけで、データの定義や関連については何も終了しないことがあります。*9。そのため、物理モデルとパーティショーン情報を事前に調べておかないと、テーブルインポートに時間を費やすかもしれません。
これを回避するには、全データディクショナリのインポート時にパーティーションをスキップします。
(原文へのリンク)
30 SQL Developer Posts in 30 Days, Day 26: Keyboarding from the Editor to the Results and Back
マウス操作はゴミ。
マウスがお好きなら、キーボードを置いて手指にステキな休暇を与えましょう。
マウス愛好者であるならば*10、本日の投稿はあなたには関係ありません。
しかし、クエリ実行後にその結果や実行計画へ移るのにマウスを触らずに済ませたいのなら、本日の投稿は金曜日の労働に対するサイコーのご褒美となるでしょう*11。
必要なのはPage Up/Downを使うキーボード・コンビネーションを覚えるだけです。
下記のGIFを見てください。
別ツールでF2
とdown
に慣れ親しんだ方の場合、SQL Developerでもそのような設定が可能です。
(原文へのリンク)
Day 27: Oracle Open World
明日は大変な日になるでしょう*12。読者の多くはここには居ないかもしませんが。
ともあれ。
皆さんは今週にデモされるソフトウェアを入手可能です。
昨日のことですがDeveloper Day VirtualBoxイメージが更新されました。最も大きなアップデートはデータベースのバージョン12.1.0.2です。In-Memoryは本当にすばらしい!
本日のTipsはありません。私はこれをタクシーの中でオラクル・ナード・ビール・ミートアップに向かいながら書いています。
んで、タクシーで書き始めて、ミートアップ中に書き終わりましたとさ。
(原文へのリンク)
30 SQL Developer Posts in 30 Days, Day 28: The SQLDev Community
今朝のことOracleナカマ60人ほどがOpen World Bridge Runイベントのためにやってきました。がんばってお外に出て、がんばって走り、30枚とか40枚とかの写真のためにがんばってジャンプしました。ありがとう! Yury!
データベースツールチームは大挙してやってきました。我々SQL Developerチームの4人*14とOracle APEX開発者からたくさんの人がこのイベントをサポートするために来てくれました。私たちはコミュニティやエンドユーザーと一緒に過ごすことを気に入っており、とりわけ私たちをせかさない人たちは良いですね*15。
もうちょっとこのイベントに浸りたいところですが、カンファレンスはもう始まっているのにそれはマズい! 今日会えない人たちとは来年には会いたいので、来年もみんなのために時間が取れるといいのだけども*16。
ともあれ、私のいいたいことはみんなに会えて楽しかったし、もちろんおニューのTシャツを着てもらったこともです。
(原文へのリンク)
30 SQL Developer Posts in 30 Days, Day 29: Preferences Revisited
今朝、SQL Developerを新しくインストールし、今週のOpen Worldのv4.1の機能に見劣ることの無い機能について、私はすぐに以下の設定を行いました。
- フォント - これについては既に触れましたが、プレゼンで見やすくするために文字サイズを大きくします。
- シングルクリックでオブジェクトを開く- Dasable
- ゼブラパターンでグリッドを表示
- NLS DATEフォーマット
ボーナスTip: Windowsであれば、フリーのZoomItが使えるか確認してみて下さい。このソフトは、プロダクトのデモ中に図形や文字を打ったりズームしたり固定したりして、プレゼンを"サイコー"にできます。
(原文へのリンク)
30 SQL Developer Posts in 30 Days, Day 30: Getting Your Data to the Web
クエリを準備した。
クエリを実行した。
それで、データをwebブラウザやアプリケーションから利用可能にするにはどうすればよいでしょうか?
HtMLとしてエクスポート
結果セットをHTMLとしてエクスポート可能で、グリッドを右クリック -> エクスポート -> HTMLします。
以下のような出力になります。
ヒントもお忘れなく
lazy-dev*18なやり方も知っておくとよいでしょう。
select /*html*/ player, team, sum(points) from hockey_stats where player in ( select player from ( select SUM(POINTS) , PLAYER from HOCKEY_STATS group by PLAYER order by SUM(POINTS) desc ) fetch first 5 rows only) group by player, team order by player, sum(points) desc;
スクリプトとして実行(F5)すると以下のような結果になります。
<html><head> <meta http-equiv="content-type" content="text/html; charset=UTF8"> <!-- base href="http://apexdev.us.oracle.com:7778/pls/apx11w/" --> <style type="text/css"> table { background-color:#F2F2F5; border-width:1px 1px 0px 1px; border-color:#C9CBD3; border-style:solid; } td { color:#000000; font-family:Tahoma,Arial,Helvetica,Geneva,sans-serif; font-size:9pt; background-color:#EAEFF5; padding:8px; background-color:#F2F2F5; border-color:#ffffff #ffffff #cccccc #ffffff; border-style:solid solid solid solid; border-width:1px 0px 1px 0px; } th { font-family:Tahoma,Arial,Helvetica,Geneva,sans-serif; font-size:9pt; padding:8px; background-color:#CFE0F1; border-color:#ffffff #ffffff #cccccc #ffffff; border-style:solid solid solid none; border-width:1px 0px 1px 0px; white-space:nowrap; } </style> <script type="text/javascript"> window.apex_search = {}; apex_search.init = function (){ this.rows = document.getElementById('data').getElementsByTagName('TR'); this.rows_length = apex_search.rows.length; this.rows_text = []; for (var i=0;i<apex_search.rows_length;i++){ this.rows_text[i] = (apex_search.rows[i].innerText)?apex_search.rows[i].innerText.toUpperCase():apex_search.rows[i].textContent.toUpperCase(); } this.time = false; } apex_search.lsearch = function(){ this.term = document.getElementById('S').value.toUpperCase(); for(var i=0,row;row = this.rows[i],row_text = this.rows_text[i];i++){ row.style.display = ((row_text.indexOf(this.term) != -1) || this.term === '')?'':'none'; } this.time = false; } apex_search.search = function(e){ var keycode; if(window.event){keycode = window.event.keyCode;} else if (e){keycode = e.which;} else {return false;} if(keycode == 13){ apex_search.lsearch(); } else{return false;} }</script> </head><body onload="apex_search.init();"> <table border="0" cellpadding="0" cellspacing="0"> <tbody><tr><td><input type="text" size="30" maxlength="1000" value="" id="S" onkeyup="apex_search.search(event);" /><input type="button" value="Search" onclick="apex_search.lsearch();"/> </td></tr> </tbody></table> <br> <table border="0" cellpadding="0" cellspacing="0"> <tr> <th>PLAYER</th> <th>TEAM</th> <th>SUM(POINTS)</th> </tr> <tbody id="data"> <tr> <td>DIONNE, MARCEL</td> <td>LAK</td> <td align="right">1307</td> </tr> <tr> <td>DIONNE, MARCEL</td> <td>DET</td> <td align="right">366</td> </tr> <tr> <td>DIONNE, MARCEL</td> <td>NYR</td> <td align="right">182</td> </tr> <tr> <td>FRANCIS, RON</td> <td>HAR</td> <td align="right">821</td> </tr> <tr> <td>FRANCIS, RON</td> <td>PIT</td> <td align="right">700</td> </tr> <tr> <td>FRANCIS, RON</td> <td>CAR</td> <td align="right">354</td> </tr> <tr> <td>FRANCIS, RON</td> <td>TOR</td> <td align="right">50</td> </tr> <tr> <td>GRETZKY, WAYNE</td> <td>EDM</td> <td align="right">1669</td> </tr> <tr> <td>GRETZKY, WAYNE</td> <td>LAK</td> <td align="right">918</td> </tr> <tr> <td>GRETZKY, WAYNE</td> <td>NYR</td> <td align="right">249</td> </tr> <tr> <td>GRETZKY, WAYNE</td> <td>STL</td> <td align="right">123</td> </tr> <tr> <td>MESSIER, MARK</td> <td>EDM</td> <td align="right">1034</td> </tr> <tr> <td>MESSIER, MARK</td> <td>NYR</td> <td align="right">691</td> </tr> <tr> <td>MESSIER, MARK</td> <td>VAN</td> <td align="right">162</td> </tr> <tr> <td>RECCHI, MARK</td> <td>PHI</td> <td align="right">777</td> </tr> <tr> <td>RECCHI, MARK</td> <td>PIT</td> <td align="right">385</td> </tr> <tr> <td>RECCHI, MARK</td> <td>MTL</td> <td align="right">370</td> </tr> <tr> <td>RECCHI, MARK</td> <td>BOS</td> <td align="right">168</td> </tr> <tr> <td>RECCHI, MARK</td> <td>ATL</td> <td align="right">88</td> </tr> <tr> <td>RECCHI, MARK</td> <td>CAR</td> <td align="right">71</td> </tr> <tr> <td>RECCHI, MARK</td> <td>TBL</td> <td align="right">45</td> </tr> </tbody></table><!-- SQL: null--></body></html>
だけどインターネットはイメージだ!
よって、クエリをチャートに落とし込みます。
ユーザ定義レポートを作成し、クエリを貼りつけ、"Chart"スタイルを設定します。フォーマット関連の作業は特に必要ありません。これは以下のようになります。
レポートの作成とスタイル設定後は、レポート上で右クリックしてHTML..
を選択すると、ディレクトリにHTMLファイル・イメージ・javascriptやリソースファイルが生成されます。
それは良い。けど、HTMLだけが欲しい……
その場合、クエリを新規アプリケーションとしてAPEXに送信することも可能です。この機能はversion 1.2から利用可能です。
それよかwebアプリでJSON出力がしたい
その場合、Oracle REST Data Servicesをセットアップしてクエリ用のRESTfulエンドポイントをセットアップするのにSQL Developerインテグレーションを使用します。これについてはKrisのブログを参照してください
勝った!30日間投稿祭、完!
長期間に渡り付き合ってくれてありがとう。受信トレイやtwitterのTLのSQL Developerの投稿で埋めちゃってお許しください! いやまじで!
私は週に1~3回の投稿頻度に戻そうと思います。v4.1がEarly Adopterが準備出来次第、多くのことを話す予定です。昨日のOpen Worldで話したことについては動画に保存しています。リンクが出来たら、共有したいと思います。
(原文へのリンク)
*1:This post was almost NULL.が原文。投稿忘れたことと、今日の題材がnullなこと、を掛けていると思われるのでエクスデス感のある訳にした。
*2:Forget the logic bits when it comes to SQL and mathsが原文。純粋にSQLと数学を扱う場合にはアンマリnullを気にしなくてもいいけど~ぐらいのニュアンスなのかな?
*3:This Baby is NULL, Zip, Nada, Zilich どれも「無」を表す言い回し。「ウチの子供が、どこにも、ここにも、あそこにも居ないの!」って感じ?
*4:National Type Like a Pirate Dayが原文。ぐぐるとwikipediaの世界海賊口調日が出てくる。9月19日は海賊っぽくしゃべる日らしい http://ja.wikipedia.org/wiki/%E4%B8%96%E7%95%8C%E6%B5%B7%E8%B3%8A%E5%8F%A3%E8%AA%BF%E6%97%A5 「コメントをよこせ!」の原文はMe comments!で、海賊っぽくとなるとこんな感じ?
*5:Ahhhh, yeah I needed those too.が原文。海賊っぽくしてみた
*6:not asking to see the errorsが原文だが上手く訳せない。直訳すれば「エラーを見ることを求めない」なので、エラーを見なかったことにする、みたいな感じなのか?
*7:Impatient?が原文。日本語的にはどう訳すのが自然なのだろうか?
*8:different ways to part and subpart your dataが原文。もしかしてパーティーションとサブパーティションの略語?
*9:And at the end of the day, it doesn’t help describe how your data is defined and related – only how it’s organized on disk.が原文。イマイチ上手く訳せない……長時間かかった上に何も終わらない、って言いたいとは思うのだけど。
*10:If you fall in the second campが原文。ちょっとなんて訳したらいいか分からなかった。推測としては、second campはこのエントリの二行目(secondなので)、「マウスが好きな人達」を指し、そういう病状にfall inしちゃってるヤツ、という意味合いなんですかね?
*11:このTipsの投稿日は9/26(金))
*12:この記事は2014/9/27に書かれており、Oracle OpenWorld 2014が9/28から開催されるため、Oracle関係者の筆者は当然多忙になることは言うまでもない。
*13:この投稿は筆者がOracle Open Worldを控えて集まってきた友人知り合いと過ごしてる、マジで個人の日記レベルであるので、訳もくだけたリア充テイストにしています。
*14:4 of us SQL Developer typesが原文。あってるか不安……
*15:especially if they are not chasing usが原文。コミュニティやエンドユーザは納期とかをせかさないから気楽だよ、ってニュアンスと思われる。
*16:For next year I will try to poll to see if we can’t find a better time, but I fear it is an impossible task to fine a time that would work for everyone.が原文。意味あってんのかスゲー不安。
*17:SYSDATE is RIGHT NOT, not ‘Today’, according to the database and will always have the time – even if you don’t see it.が原文で、ゴチャゴチャ書いてるけど、SYSDATEはDBサーバの時刻を返し、場合によってはサーバの値を直接参照することはできない、と言っているのだと思われる。
*18:何と訳すのが良いんだろうか? 少ない手間で最大限の効果、的な意味なので、手抜きとか?
*19:I did this a long time ago, and I’m NOT an APEX developer…but you can do this pretty easily.が原文。APEX良く知らなくても簡単に使えるよ、って意味なのかな?