PostgreSQL is an object-relational database management system.
We have two question:
Index on expression
CREATE INDEX foo_name_first_idx
ON foo ((lower(substr(foo_name, 1, 1))));
for selects
SELECT * FROM foo
WHERE lower(substr(foo_name, 1, 1)) = 's';
Index refers to the predicate WHERE
CREATE INDEX access_log_client_ip_ix ON access_log (client_ip)
WHERE NOT (client_ip > inet '192.168.100.0' AND
client_ip < inet '192.168.100.255');
for selects
SELECT * FROM access_log
WHERE client_ip = '192.168.100.45';
Instead
CREATE INDEX sales_quantity_index ON sales_table (quantity);
this better for huge table
CREATE INDEX CONCURRENTLY sales_quantity_index ON sales_table (quantity);
but be careful
Indexes:
"idx" btree (col) INVALID
Buying a bigger box is quick(ish). Redesigning software is not.
37 Signals Basecamp upgraded to 128 GB DB server: don’t need to pay the complexity tax yet
CREATE TABLE my_logs(
id SERIAL PRIMARY KEY,
logdate TIMESTAMP NOT NULL,
data JSON
);
CREATE TABLE my_logs2012m10 (
CHECK ( logdate >= DATE '2012−10−01' AND logdate < DATE '2012−11−01' )
) INHERITS (my_logs);
CREATE INDEX my_logs2012m10_logdate ON my_logs2012m10 (logdate);
Simple cleanup
DROP TABLE my_logs2012m06;
or remove partition from partitioning
ALTER TABLE my_logs2012m06
NO INHERIT my_logs;
partitioning_test=# EXPLAIN SELECT ∗ FROM my_logs WHERE logdate > '2012−08−01';
QUERY PLAN
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Result ( cost =6.81..41.87 rows=660 width=52)
−> Append ( cost =6.81..41.87 rows=660 width=52)
−> Bitmap Heap Scan on my_logs ( cost =6.81..20.93 rows=330 width=52)
Recheck Cond: ( logdate > '2012−08−01 00:00:00' : : timestamp without time zone)
−> Bitmap Index Scan on my_logs_logdate ( cost =0.00..6.73 rows=330 width=0)
Index Cond: (logdate > '2012−08−01 00:00:00' : : timestamp without time zone)
−> Bitmap Heap Scan on my_logs2012m08 my_logs ( cost =6.81..20.93 rows=330 width=52)
Recheck Cond: ( logdate > '2012−08−01 00:00:00' : : timestamp without time zone)
−> Bitmap Index Scan on my_logs2012m08_logdate ( cost =0.00..6.73 rows=330 width=0)
Index Cond: (logdate > '2010−08−01 00:00:00' : : timestamp without time zone)
(10 rows)
What I want?
How about hstore?
Advantages:
Disadvantages:
{ +
"name": "Litzy Satterfield", +
"age": 24, +
"siblings": 2, +
"faculty": false, +
"numbers": [ +
{ +
"type": "work", +
"number": "684.573.3783 x368"+
}, +
{ +
"type": "home", +
"number": "625.112.6081" +
} +
] +
}
$ SELECT * from json_demo;
id | username | email | posts_count
----+----------+-------------------+-------------
1 | john | john@gmail.com | 10
2 | mickael | mickael@gmail.com | 50
(2 rows)
$ SELECT row_to_json(json_demo) FROM json_demo;
row_to_json
----------------------------------------------------------------------------
{"id":1,"username":"john","email":"john@gmail.com","posts_count":10}
{"id":2,"username":"mickael","email":"mickael@gmail.com","posts_count":50}
(2 rows)
$ SELECT array_to_json(array_agg(json_demo)) FROM json_demo;
array_to_json
----------------------------------------------------------------------------
[{"id":1,"username":"john","email":"john@gmail.com","posts_count":10},
{"id":2,"username":"mickael","email":"mickael@gmail.com","posts_count":50}]
(1 row)
why javascript?
v8 javascript engine
CREATE OR REPLACE FUNCTION
psqlfib(n int) RETURNS int AS $$
BEGIN
IF n < 2 THEN
RETURN n;
END IF;
RETURN psqlfib(n-1) + psqlfib(n-2);
END;
$$ LANGUAGE plpgsql IMMUTABLE STRICT;
select n, psqlfib(n)
from generate_series(0,30,5) as n;
n | psqlfib
----+---------
0 | 0
5 | 5
10 | 55
15 | 610
20 | 6765
25 | 75025
30 | 832040
(7 rows)
Time: 34014.299 ms
CREATE OR REPLACE FUNCTION
fib(n int) RETURNS int as $$
function fib(n) {
return n<2 ? n : fib(n-1) + fib(n-2)
}
return fib(n)
$$ LANGUAGE plv8 IMMUTABLE STRICT;
select n, fib(n)
from generate_series(0,30,5) as n;
n | fib
----+--------
0 | 0
5 | 5
10 | 55
15 | 610
20 | 6765
25 | 75025
30 | 832040
(7 rows)
Time: 33.430 ms
CREATE OR REPLACE FUNCTION
fib2(n int) RETURNS int as $$
var memo = {0: 0, 1: 1}
function fib(n) {
if(!(n in memo))
memo[n] = fib(n-1) + fib(n-2)
return memo[n]
}
return fib(n);
$$ LANGUAGE plv8 IMMUTABLE STRICT;
select n, fib2(n)
from generate_series(0,30,5) as n;
n | fib2
----+--------
0 | 0
5 | 5
10 | 55
15 | 610
20 | 6765
25 | 75025
30 | 832040
(7 rows)
Time: 0.535 ms
CREATE TABLE members ( profile json );
SELECT count(*) FROM members;
count
---------
1000000
(1 row)
Time: 201.109 ms
CREATE OR REPLACE FUNCTION get_numeric(json_raw json, key text)
RETURNS numeric AS $$
var o = JSON.parse(json_raw);
return o[key];
$$ LANGUAGE plv8 IMMUTABLE STRICT;
SELECT * FROM members WHERE get_numeric(profile, 'age') = 36;
Time: 9340.142 ms
CREATE INDEX member_age ON members (get_numeric(profile, 'age'));
SELECT * FROM members WHERE get_numeric(profile, 'age') = 36;
Time: 57.429 ms
CREATE OR REPLACE FUNCTION
valid_json(json text)
RETURNS BOOLEAN AS $$
try {
JSON.parse(json); return true;
} catch(e) {
return false;
}
$$ LANGUAGE plv8 IMMUTABLE STRICT;
CREATE DOMAIN json AS TEXT
CHECK(valid_json(VALUE));
$ INSERT INTO members
VALUES('not good json');
ERROR: value for domain json
violates check constraint "json_check"
$ INSERT INTO members
VALUES('{"good": "json", "is": true}');
INSERT 0 1
$ select * from members;
profile
------------------------------
{"good": "json", "is": true}
(1 row)
explain analyze select count(*) from members where
get_numeric(profile, 'age')=26 and get_numeric(profile, 'siblings')=1;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------
Aggregate (cost=301.38..301.39 rows=1 width=0) (actual time=106.420..106.420 rows=1 loops=1)
-> Bitmap Heap Scan on members (cost=190.46..301.31 rows=25 width=0) (actual time=92.641..104.634 rows=6911 loops=1)
Recheck Cond: ((get_numeric(profile, 'siblings'::text) = 1::numeric) AND (get_numeric(profile, 'age'::text) = 26::numeric))
-> BitmapAnd (cost=190.46..190.46 rows=25 width=0) (actual time=89.192..89.192 rows=0 loops=1)
-> Bitmap Index Scan on member_siblings (cost=0.00..95.10 rows=5000 width=0) (actual time=72.387..72.387 rows=339432 loops=1)
Index Cond: (get_numeric(profile, 'siblings'::text) = 1::numeric)
-> Bitmap Index Scan on member_age (cost=0.00..95.10 rows=5000 width=0) (actual time=7.725..7.725 rows=13732 loops=1)
Index Cond: (get_numeric(profile, 'age'::text) = 26::numeric)
Total runtime: 106.492 ms
(9 rows)
create or replace function mustache(template text, view json)
returns text as $$
// …400 lines of mustache.js…
return Mustache.to_html(template, JSON.parse(view))
$$ LANGUAGE plv8 IMMUTABLE STRICT;
select mustache(
'hello {{#things}}{{.}} {{/things}}:) {{#data}}{{key}}{{/data}}',
'{"things": ["world", "from", "postgresql"], "data": {"key": "and me"}}'
);
mustache
---------------------------------------
hello world from postgresql :) and me
(1 row)
Time: 0.837 ms
"NoSQL" database
Contact information