PostgreSQL Part.11©2ch.net
■ このスレッドは過去ログ倉庫に格納されています
で、なんでそんな物理的事情で並んだ順で返すのかって言ったら、『一々ソーティングしなくていいから少しでも速く、省メモリで結果返して欲しいって時に勝手にソーティングされたら寧ろ迷惑だろ、ソーティングは通常ではなくオプションとすべきだ』ってことでないの? >>170
クラスタ化インデックスだとpk順になる。 >>170
そんなのどんなRDBMSでも同じで、実装を考えれば、そうなるだろうが。 >>171
違う。RDBのレコードはソート指定をしないかぎり不定というのが標準SQLでの仕様だから。 PHP+PostgreSQLで運用する場合、元号の処理ってどうしてる?
自分でしか使わないシステムなので、極力西暦で通すか、どうしても必要な場合は1988引いてるけど(基本的に昭和のデータは扱わない)、今度の改元がなぁ >>176
データベースだというのに西暦→和暦マスタテーブルを作ろうという発想がないことに驚く >>176
昭和99年とかの特殊な要件がなければ内部は西暦、外部とのやり取り時に変換が普通かと >>176
表示なり入力なりエンドユーザに一番近いところで変換したいな
そもそも元号という「汚い」ものを可能な限り扱いたくないし、
Postgres用の変換はおそらく自作が必要だが、PHPやJS用なら適当に拾ってこれるから >>177
マスタテーブルだけで変換しようとすると、年の途中での改元に対応しないといけないんで、1日あたり1レコード要るんじゃね?
100年で36,525か36,524になっちゃう >>180
アホくさ。なんで年号が変わらない部分の日の単位でデータを持つんだよ。
それじゃあ自分の生年月日を書くのに今日からさかのぼって一日ごとに列挙して書くようなもんだろw 明治:1868-01-25 〜 1912-07-29
大正:1912-07-30 〜 1926-12-24
昭和:1926-12-25 〜 1989-01-07
平成:1989-01-08 〜
これをどうUIに反映するかは、各自の考え方だろう。 インデックスについて教えてください。
調べましたが「検索が早くなる場合もあるらしい」くらいしか分かりませんでした。
・ インデックスは作成するだけでよいのか?
検索時に作成したインデックスを指定したりしなくてよいのか。
調べた限り指定する方法がなかったため、作成するだけで効果があるように見えた。
・ REINDEXでのロック時の挙動
インデックスがロックされると聞いた。
インデックスがロックされるだけで検索自体は可能なのか。
・ とりあえずインデックスを作成しておけばよいのか?
インデックスがそんなに便利なものなら、ハードディスクの容量が許す限り、
検索しそうなものは片っ端からインデックスを作成しておけばよいのか。 >>186
> ・ インデックスは作成するだけでよいのか?
はい。
インデックスを使った方が検索コストが低い場合は、自動的に使われます。
> ・ REINDEXでのロック時の挙動
> インデックスがロックされるだけで検索自体は可能なのか。
いいえ。検索もブロックされます。
通常はreindexする必要はありません。
将来、reindexが必要だと感じたら(容量が増大したなどの場合)、どう対処するのが
良いか検索するとよいです。
> ・ とりあえずインデックスを作成しておけばよいのか?
いいえ。
インデックスがあるということは、INSERT/DELETEのときにデータ本体だけでなく
インデックスそのものも更新する必要があります。
単純に言えば、処理時間が増えるということです。
不要なインデックスは生成しないようにするのが良いです。 日本語扱うならencodeはCだろって言う人を結構見る気がしますが、なぜutf8じゃ駄目なんでしょうか? 例えばこの人
http://soudai1025.blogspot.jp/2015/03/postgresqlunicode-6.html
> なお、検証した環境のPostgreSQLのlocale指定はC(nolocale)としています。
> (日本語を扱う場合はほとんどの場合はCを指定するでしょうし) えっ・・・
今まで作ったシステム、全部utf8にしてきてしもうた・・・ encodeとlocaleは別だぞ。
encode=utf8 かつ locale=C が推奨なのはよく見る。
Linux (glibc) はlocaleの実装をサボっているので、C以外に設定しても性能が落ちるだけで何の利点もない。
Windowsなら文字列の比較やソートに差が出るので、用途に適して選べばいい。 initdb --encoding=UTF8 --no-locale ←これが基本かなと >>193
Linuxでも当然ながら差が出る。
なぜなら、文字コードは辞書順には並んでないから。 >>196
どんな文字コードでも漢字の並び順は、日本人が見ても意味のある順番になってないからな。 >>196
Linuxもまともになったのか?
昔使ったときはlocale=ja系でも変わらず文字コード順に並べられたんだが >>198
「辞書順」の正しい定義を知らないけど、少なくとも文字コード順には並ばないよ。
create table foo(s text)に、漢数字の'一'から'九'をインサートし、以下のクエリを実行。
select array_agg(s) from (select s from foo order by s) as t;
locale=C -> {一,七,三,九,二,五,八,六,四} -- 文字コード順
locale=ja_JP.UTF-8 -> {一,九,五,三,四,七,二,八,六} -- 辞書(?)順 文字コード順でも辞書順でも、それを正解とするかどうかは要件次第。
ちなみに漢数字は、訓読み順で並んでいる。 >>199
理解した。Linuxでも順序は変わるね。
ひらがな/カタカナの濁/半濁の扱いは今でも差があるようだ。設計思想?互換性?
msvcrt: ハはバばパぱ
glibc : はばぱハバパ
環境依存が怖い。要件次第だが、自前で「ふりがな」列を用意したほうがマシだな。 他人に公開する予定の無い、自分専用のwebサイトを作る場合でもSQLインジェクション対策はしておいた方がいいよね?
クラスを転用するときに問題になるし、悪意が無くてもエラーのもとだし >>203
言語によるけど今時パラメータクエリぐらいは使えるだろうから普通にパラメータクエリでやるわな
あとから見てもその方がわかりやすいし >>205
PHPで言えば、pg_query_params()とか? phpって対策されていないやつ
非推奨じゃなかったっけ
おいらはPDOでやってるかな ぽすとぐれすきゅーえる
ぽすとぐれすえすきゅーえる TIMESTAMP (WITHOUT TIMEZONE)とCURRENT_TIMESTAMPについて教えてください。
INSERTにてCURRENT_TIMESTAMPで入れたあと、SELECTで取り出すと日本時間になっています。
どの時点で日本時間になっているのでしょうか?
1. CURRENT_TIMESTAMPの時点ではJSTだが、INSERTするときにJSTがUTCに変換されて保存され、
SELECTで取り出すときにシステムの時刻を見て+0900されている
2. CURRENT_TIMESTAMPの時点ではJSTで取得されるが、
元々これにタイムゾーンのデータはなく、そのまま保存され、
SELECTで取り出すときは同じシステム時刻を使ってるからたまたま同じタイムゾーンとして取得されている
3. CURRENT_TIMESTAMPの時点ではUTCで取得され、保存もUTCだが
SELECTで取り出すときはシステム時刻を参照して勝手にJSTにしている
4. その他の未知の仕組み >>210
http://www.postgresql.jp/document/current/html/datatype-datetime.html
> 通常timestamp without time zoneの値はtimezoneのローカル時間としてみなされる
とあるから、言葉通りだとするなら:
・INSERTするときに時刻の値だけを保存する (+0900を無視)
・SELECTするときに現在のタイムゾーン扱い (+0900を追加)
SET TIMEZONE TOしながら試してみれば検証できるかも >>210
まず前提として、without time zoneをselectした結果にはtime zone情報はないのだから、UTCもJSTもない。
次にcurrent_timestampは、tz情報付きのデータ。
それをwithout time zone絡むにインサートすると、tz情報は切り捨てられる。(たとえば、"2017-05-12 18:00:00")
そのデータを、日本で取得しようがアメリカで取得しようが、tz情報なしの"2017-05-12 18:00:00"が取得される。
つまり、アメリカで取得した人は、現地時間の"2017-05-12 18:00:00"だと見えるということ。 >>211-212
ありがとうございます。
世界向けのSNSを作ろうとしたのですが、これがネックで
時間部分の設計ができない状態でした。
助かります。 お世話になります。
psql で database ごとに history を分けて表示したい (\s) のですが、
(他の databae の history を表示したくない)
どうやったらいいのでしょうか?
よろしくお願いします。 historyって、homeの .psql_history 出してるだけだからなあ
db切り替えるたびにリネームするとか? ああ、そういう仕組みなんですね。
複数の database をそれぞれ別々に psql で開いたりしてるんですけど、じゃぁ、全然無理ですね。
わかりました、ありがとうございました。 >>217
そのものズバリですね♪
ありがとうございます。
おかげで、.psqlrc っていう設定ファイルのことも知りました。
PostgreSQL の Documentation にありますね。
かさねがさねありがとうございました。 拡張を使った場合、メジャーバージョンが変わるときのアップグレードで使えなくなったり作業が増えたりするのでしょうか?
スキーマのバージョンが変わっている拡張があったら何かしないといけないとか? >>221
> 30分単位とかで時間を丸めてくれる関数ないですか
自作すれば? トリガのデバッグってどうやってますか?
初めてトリガ関数作ります >>224
普通に、クエリ後、関連データを取得してassert >>225
ASSERT文、調べました。
そういうのがあるんですね♪
ありがとうございました >>226
たぶん勘違いしてる
クライアントコードを実装する、JavaとかPHPとかのプログラミング言語で普通にチェックしろってこと
IDEでステップ実行とかできないからね >>227
> クライアントコードを実装する、JavaとかPHPとかのプログラミング言語で普通にチェックしろってこと
そうなの?
それなら俺も勘違いしてたわ。 ASSERTがどうのってのはPL/pgSQLの機能でしょ
https://www.postgresql.jp/document/current/html/plpgsql-errors-and-messages.html
トリガ関数をどの言語で作るかにもよるけど
たいていはサーバーログにメッセージを書き出す、いわゆるprintfデバッグになるのでは そう思う。自立型トランザクションを使えばログ表に対するcommitを必ずしながら
トリガー本来の処理ではrollback等もできる。多分10g以降の機能で9iでは不可。 >>229
普通にデータベースにアクセスするメソッドをテストする方法と同じだよ。
確認する項目が、トリガーが変更したデータも対象になるってだけで。
普通にデータベースにアクセスするメソッドをテストするときもprintfデバッグしてたら、
トリガーのテストもそうなるだろうけど、普通はコードで確認するんじゃないか? ゴメン。Oracleと勘違いしてた。>>230 は無視して >>231
トリガだと「普通のアクセス」とはデバッグ方法が違いそう、ってのが質問の意図じゃないの?
それを「同じだよ」で済ませるのは会話が噛み合っていない感がある
トリガの内部で何が起きているかのデバッグにはprintf程度しか道具が無いんじゃないかな?
トリガの結果が適切かを確認するにはテストコードを使うのはわかる 日本語メッセージでGSSAPIがGSSAIになっちゃってるところがある >>233
> トリガの内部で何が起きているかのデバッグにはprintf程度しか道具が無いんじゃないかな?
内部が正しいと確信が持てるだけのテストをすればいいだけ。
てか、トリガーのコードじゃなくて、ホストプログラムのコードだってそうだろ?
まぁ、途中で変数の中身を見ないと、なにが行われているのかわかれないスキルレベルだったら話は違うが。 >>235
ホワイトボックステストも知らないなら絡んでくるなよ >>236
いや、ホワイトボックステストの話をしてるつもりだが。
TDDはホワイトボックステストだが、やることは、
・前提条件を作る
・テスト対象のメソッドを呼ぶ
・結果を確認する
を、自分の確証が持てるまでやる。
トリガーをテストする場合も同じ。
トリガーをキックするメソッドを呼び出すか、あるいは直接INSERT/UPDATE/DELETEを実行し、
トリガーが変更した内容を、実際にデータを取得してassertする。
C0カバレッジで満足できるならそこでやめる。
確証が持てないなら、C1カバレッジになるようなテストを追加する。 >>237
テストのやり方はそれでいいけど、テストが失敗してなおかつ原因がよくわからないときの話じゃないかな
そういうときは、raise noticeがやっぱり最強だと思う トリガーはいいとして、複雑なクエリのデバッグはどうやるつもりなんだろうか
それこそ、printfも使えない >>237
背伸びしすぎ
> TDDはホワイトボックステストだが
TDD の話なんて誰もしてない
最近知って話したくてしょうがないのか? w
そもそも TDD はコードを作る前にテストケースを作るからホワイトボックステストにはならない
むしろ仕様からテストケースを作るのでテストケースの作り方としてはブラックボックステストに近い
> ・前提条件を作る
> ・テスト対象のメソッドを呼ぶ
> ・結果を確認する
その前提条件の作り方の話だぞ
> を、自分の確証が持てるまでやる。
違う、ホワイトボックステストでは内部のコードを考慮してテスト条件を作るんだよ
それがわかってないから
> トリガーをキックするメソッドを呼び出すか、あるいは直接INSERT/UPDATE/DELETEを実行し、
> トリガーが変更した内容を、実際にデータを取得してassertする。
なんてアホなことを言い出す IPAのデータベーススペシャリスト持ってない奴は書き込むなよ デバッグしたいと言ってるやつの目的がわからない。
テストと混同しているみたいでやばそうだな。 >>241
TDDのわかってない奴と議論しても時間の無駄なんで、これでも読んで。
https://ja.wikipedia.org/wiki/%E3%83%86%E3%82%B9%E3%83%88%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA
> 違う、ホワイトボックステストでは内部のコードを考慮してテスト条件を作るんだよ
C0, C1カバレッジの意味わかってるか?
それを網羅しなければ自信がもてない場合は、それをカバーするテストを納得できるまで追加するんだよ。 >>241
つか、お前、データベースアクセスを含むクラス・メソッドの単体レベルのテストはやってるのか?
やってるとしたら、どうやってんだ?
テストコード書いてるなら、トリガーがあろうとなかろうと関係ないことは自明だろ。 plpgsqlは実行しないとtypoなんかがわからないので、c0必須 >>247
これな
存在しないシンボル名使ってたら、CREATEでエラーにしてくれって話だ raise notice方法の良くないところは、リリース時にそれを削除する必要があること
トリガーをダンプしてバージョン管理とかしてると、ただそれだけでリビジョンが進む
そして、それを忘れやすい データベース内で完結するテスト方法は苦行なんで、
普通にプログラムからクエリを実行してテストしたほうがいいよ >>245
Wikipedia なんて底が浅すぎ w
コードを見てテストケースを作るなんて書いてないだろ?
C0, C1 は結果の話
根本的に理解してないのがバレバレだぞ w
>>246
それトリガーの話じゃないだろ
まあ必死だな、ってだけ言っとくよ w >>252
あ、「クエリを発行して」の言いまちがいね >>253
発行も実行も普通は同じ意味で使われる。 データベースに詳しくないのが、何かの言語と結合してテストするようなのとを言ってるけど、それおかしいから。
データベース軽視なんだろうな。 もともとトリガのテストがしたいという話だが、トリガとトリガが呼び出す関数をいきなり一緒にテストしようとしているのが間違い。
関数は関数でテストして、トリガはトリガがテストして、結合テストはデータのIN/OUTで確認すればいいだけ。
データ観点のテストをあまりしないやつらはかなりいるが、とんでもないから無視した方がいい。 トリガープロシージャって普通の関数として単体で実行できるんだっけ?
やったことないけど、OLDとかNEWとかどう与えるんだろう。 >>257
Oracleのトリガーと混同してたわ。トリガ関数に普通の関数を呼び出すようにしてないとできないな。 >>254
いや全然意味違うけどw
始めて本当に日本語勉強した方がいい人見つけたw >>256
> トリガープロシージャって普通の関数として単体で実行できるんだっけ?
>>237でも言ったが、トリガー関数単体では実行できないので、トリガーのみをテストしたいなら、
INSERT/DELETE/UPDATEを実行して結果を確かめれば良い。
USERSテーブルにINSERTすると、どこかのテーブルのユーザ数合計がトリガーで更新されるとき、
function testUserCountSucc()
{
prevCount = getPrevUserCount();
db->execute("INSERT INTO USERS ...");
currCount = getPrevUserCount();
assertEquals(prevCount + 1, currCount);
}
自分がそのトリガーを実装する場合は、トリガー内のIFやFORがどういう条件でどうなるかは
わかるはずなので、C0カバレッジになるようにテストケースを増やせば良い。
「ユーザを追加するとユーザ数合計が更新される」というのが、ホストコードで実装されるのか
トリガーで実装されるのかを「実装詳細」と考えるなら、実は上のやり方は好ましくない。
Users::Add()をテストするどこかで、ユーザ数合計が更新されているassertionを追加したほうが良い。 s/getPrevUserCount/getUserCount/ なんかもっといろいろ間違ってた。
最初のアンカーは、256じゃなくて>>257
> C0カバレッジ
↓
> C0カバレッジ100% >>256
どういう意味で結合テストっていってるのかしらんけど、単体テストでもデータのIN/OUTで確認するだろ 「発行」するのは人またはプログラム、「実行」するのはRDBMS、という原理主義者なのか? >>265
そういうことじゃなくて、俺謎理論だと思うよ >>255
DB内で完結するテスト例:http://pgtap.org/
苦行
あえて選ぶなら止めないが >>268
・普通のプログラムでは簡単に書ける「共通処理」が書きづらい
→ まぁ、functionで実装していけばいいが、以下の考慮が必要になる
・テストを変更するのにいちいちmigrationが必要
・テストはテスト対象と同一データベース内におく必要がある
・故に、CIでテストしようとすると全員のテストを一つのDBに入れる必要がある
・そうすると、他人とシンボル名が重複しないようにするなどの配慮が必要だとわかる
・スキーマで分割すればいいじゃんとか思う
・グダる
普通にコードで書くのが楽よ >>269
コードって別の言語だし、ユーザー、スキーマは結合テストレベルでは本番環境に無理に合わせない。
なんでいきなりシステムテストレベルで確認しようとするのか?
まあ小さいパッケージやWebサイト屋だとそういうテストをする会社や人間が存在するのは知っているが。 ■ このスレッドは過去ログ倉庫に格納されています