Postgres The First Experience
Postgres The First Experience
We have written this small book for those who only start
getting acquainted with the world of PostgreSQL. From this
book, you will learn:
We hope that our book will make your first experience with
PostgreSQL more pleasant and help you blend into the Post-
greSQL community. Good luck!
3
i
I About PostgreSQL
PostgreSQL is the most feature-rich free open-source data-
base system. Developed in the academic environment, it has
brought together a wide developer community through its
long history. Nowadays, PostgreSQL offers all the functional-
ity required by most customers and is actively used all over
the world to create high-load business-critical systems.
Some History
Development
Support
Current State
Security
Transaction Support
Query Planner
Indexing
• Hash,
a hash-based index. Unlike B-trees, such indexes work
only for equality checks, but can prove to be more efficient
and compact in some cases.
• GiST,
a generalized balanced search tree. This access method is
used for the data that cannot be ordered. For example, R-
trees that are used to index points on a surface and allow
to implement fast k-nearest neighbors (k-NN) search, or
indexing overlapping intervals.
• SP-GiST,
a generalized non-balanced tree based on dividing the
search range into non-intersecting nested partitions. For
example, quad-trees for spatial data and radix trees for
text strings.
• GIN,
a generalized inverted index, which is used for compound
multi-element values. It is mainly applied in full-text
search to find documents that contain the word used in
the search query. Another example is search of elements
in data arrays.
12 • RUM,
i an enhancement of the GIN method for full-text search.
Available as an extension, this index type can speed up
phrase search and return the results sorted by relevance.
• BRIN,
a compact structure that provides a trade-off between the
index size and search efficiency. Such index is useful for
big clustered tables.
• Bloom,
an index based on Bloom filter. Having a compact repre-
sentation, this index can quickly filter out non-matching
tuples, but requires re-checking of the remaining ones.
Many index types can be built upon both a single column and
multiple columns. Regardless of the type, you can build in-
dexes not only on columns, but also on arbitrary expressions,
as well as create partial indexes for specific rows. Covering
indexes can speed up queries as all the required data is re-
trieved from the index itself, avoiding heap access.
Cross-Platform Support
• data types
• functions and operators to support new data types
• index and table access methods
• server programming languages
• foreign data wrappers
• loadable extensions
• CitusDB,
which implements data distribution between different
PostgreSQL instances (sharding) and massively parallel
query execution.
• PostGIS,
one of the most popular and powerful geo-information
data processing systems.
Independence
Partitioning
Indexes
You can now choose between custom and generic plans for
prepared statements using a server parameter. Previously,
there was no way to forbid the use of generic plans, which
could lead to non-optimal query execution.
TOAST now allows to extract only the initial part of the value
that is actually required instead of fully decompressing the
toasted value and removing the redundant part, as before.
Monitoring
Logging queries can generate huge log files. Now you can log
only a specific percent of all transactions, which is especially
useful for OLTP systems with multiple similar transactions.
(The ability to log only some of the “short” operations is tar-
geted for the next version.)
One more wait event has been added: fsync for WAL files. It
allows to receive more details about I/O performance.
VACUUM and ANALYZE commands can now skip tables that can-
not be locked, and do not request a lock on tables for which
the user lacks permissions.
You can also specify the wraparound horizon for the vacu-
umdb utility to focus on cleaning up those tables that need
it the most.
Empty leaf pages of GiST indexes are now deleted during vac-
uum operation.
You can also find many more inconspicuous, but very useful
improvements.
SQL Commands
You can filter rows when copying data from a file into a table
using COPY FROM.
Utilities
SQL/JSON Support
Miscellaneous
Installation
Choose components:
Keep all options selected if you are uncertain which ones to 25
choose. iii
You can leave the default settings in all the other fields.
27
iii
Installation
$ locale
30 If you plan to store data in a language other than English,
iii the LC_CTYPE and LC_COLLATE variables must be set appro-
priately. For example, for the French language, make sure to
set these variables to “fr_FR.UTF8”:
$ export LC_CTYPE=fr_FR.UTF8
$ export LC_COLLATE=fr_FR.UTF8
You should also make sure that the operating system has the
required locale installed:
• /etc/postgresql/12/main/postgresql.conf is the
main configuration file that contains server parameters.
• /etc/postgresql/12/main/pg_hba.conf file defines
access settings. For security reasons, the default con-
figuration only allows access from the local system on
behalf of the database user that has the same name as
the current OS user.
Now it’s time to connect to the database and try out SQL.
IV Trying SQL
Connecting via psql
Databases
postgres=# \c test
You are now connected to database "test" as user
"postgres".
test=#
The command that we’ve just entered does not look like SQL,
as it starts with a backslash. This is a convention for special
commands that can only be used in psql (so if you are us-
ing pgAdmin or another GUI tool, skip all commands starting
with a backslash, or try to find an equivalent).
There are quite a few psql commands, and we’ll use some of
them a bit later.
36 To get the full list of psql commands right now, you can
iv run:
test=# \?
Tables
• integer
• text
• boolean, which is a logical data type taking true or false
values
You can find the exact syntax of the CREATE TABLE com-
mand in documentation, or view command-line help right
in psql:
Simple Queries
To read data from tables, use the SQL operator SELECT. For
example, let’s display two columns of the courses table:
The result can contain several rows with the same data. Even
if all rows in the original table are different, the data can
appear duplicated if not all the columns are displayed:
In general, you can use any expressions after the SELECT op-
erator. If you omit the FROM clause, the resulting table will
contain a single row. For example:
Joins
In this example, the result does not include the rows of the
original table that do not have a pair in the other table: al-
though the condition is applied to the subjects, the students
that did not take an exam in this subject are also excluded. To
include all the students into the result, use the outer join:
Subqueries
test=# SELECT *
FROM exams
WHERE (SELECT start_year
FROM students
WHERE students.s_id = exams.s_id) > 2014;
s_id | c_no | score
------+-------+-------
1556 | CS301 | 5
(1 row)
Let’s display all students who have any scores in the specified
course:
There is also the NOT IN form of this predicate that returns the
opposite result. For example, the following query returns the
list of students who got only excellent scores (that is, who
didn’t get any lower scores):
Sorting
Here the rows are first sorted by score, in the ascending order.
For the same scores, the rows get sorted by student ID card
number, in the ascending order. If the first two keys are the
50 same, rows are sorted by the course number, in the descend-
iv ing order.
Grouping Operations
In queries that use grouping, you may need to filter the rows
based on the aggregation results. You can define such con-
ditions in the HAVING clause. While the WHERE conditions are
applied before grouping (and can use the columns of the orig-
inal tables), the HAVING conditions take effect after grouping
(so they can also use the columns of the resulting table).
Let’s select the names of students who got more than one
excellent score (5), in any course:
Transactions
test=# \d students
Table "public.students"
Column | Type | Modifiers
------------+---------+----------
s_id | integer | not null
name | text |
start_year | integer |
g_no | text |
...
You can also get the list of all tables available in the
database:
test=# \d
List of relations
Schema | Name | Type | Owner
--------+----------+-------+----------
public | courses | table | postgres
public | exams | table | postgres
public | groups | table | postgres
public | students | table | postgres
(4 rows)
54 Now let’s create a group “A-101” and move all students into
iv this group, making Anna its monitor.
test=# BEGIN;
BEGIN
The second session still gets consistent data, which was al-
ready present in the database when the uncommitted trans-
action started.
test=# COMMIT;
COMMIT
Third, as the example has shown, other users will never see
inconsistent data not yet committed by the transaction. This
property is called isolation. Thanks to this property, the
database system can serve multiple sessions in parallel, with-
out sacrificing data consistency. PostgreSQL is known for a
very effective isolation implementation: several sessions can
run read and write queries in parallel, without locking each
other. Locking occurs only if two different processes try to 57
change the same row simultaneously. iv
Conclusion
test=# \q
58 Useful psql Commands
iv
\? Command-line reference for psql.
\l List of databases.
General Information
Each flight goes from one airport to another. Flights with the
same flight number have the same points of departure and
destination, but different departure dates.
Flights
# flight_id
Tickets flight_no
Ticket_flights
∗
scheduled_departure Aircrafts
# ticket_no
∗
# ticket_no scheduled_arrival
book_ref # aircraft_code
∗
# flight_id departure_airport
∗
passenger_id
∗
fare_conditions arrival_airport
∗ ∗ model
passenger_name
∗ ∗
amount status
∗ ∗ range
contact_data
∗ ∗
aircraft_code
∗
∗
◦ actual_departure
◦ actual_arrival
Boarding_passes
Seats
# ticket_no
# aircraft_code
# flight_id
# seat_no
∗ boarding_no
seat_no
∗ fare_conditions
∗
v
61
1
62
v
Bookings 63
v
To fly with our airline, passengers book the required tickets
in advance (book_date, which must be not earlier than one
month before the flight). The booking is identified by its
number (book_ref, a six-position combination of letters and
digits).
Tickets
Note that neither the passenger ID, nor the name is perma-
nent (for example, one can change the last name or passport),
so it is impossible to uniquely identify all tickets of a particu-
lar passenger. For simplicity, let’s assume that all passengers
are unique.
Flight Segments
Each flight segment has its price (amount) and travel class
(fare_conditions).
64 Flights
v
The natural key of the flights table consists of two fields:
the flight number flight_no and the departure date sched-
uled_departure. To make foreign keys a bit shorter, a surro-
gate key flight_id is used as the primary key.
Each flight has a scheduled date and time of departure and ar-
rival (scheduled_departure and scheduled_arrival). The
actual departure and arrival times (actual_departure and
actual_arrival) may differ: the difference is usually not
very big, but sometimes can be up to several hours if the
flight is delayed.
• Scheduled
The flight is available for booking. It happens one month
before the planned departure date; before that time, there
is no entry for this flight in the database.
• On Time
The flight is open for check-in (twenty-four hours before
the scheduled departure) and is not delayed.
• Delayed
The flight is open for check-in (twenty-four hours before
the scheduled departure), but is delayed.
• Departed
The aircraft has already departed and is airborne.
• Arrived 65
The aircraft has reached the point of destination. v
• Cancelled
The flight is cancelled.
Airports
Boarding Passes
Aircraft
Seats
Flights View
• edu.postgrespro.com/demo-small-en.zip
A small database with flight data for one month (21 MB,
DB size is 280 MB).
• edu.postgrespro.com/demo-medium-en.zip
A medium database with flight data for three months
(62 MB, DB size is 702 MB).
• edu.postgrespro.com/demo-big-en.zip
A large database with flight data for one year
(232 MB, DB size is 2638 MB).
$ sudo su - postgres
$ wget https://edu.postgrespro.com/demo-small-en.zip 69
v
Then run the following command:
postgres# \i demo-small-en-20170815.sql
If the file is not found, check the “Start in” property of the
shortcut; the file must be located in this directory.
Sample Queries
postgres=# \c demo
You are now connected to database "demo" as user
"postgres".
70 All the entities we are interested in are stored in the book-
v ings schema. When you are connected to the database, this
schema is used automatically, so there is no need to specify
it explicitly:
If you would like to define this setting globally, run the fol-
lowing command:
demo=# \c
You are now connected to database "demo" as user
"postgres".
demo=# SELECT airport_code, city
FROM airports LIMIT 3;
airport_code | city
--------------+--------------------------
YKS | Якутск
MJZ | Мирный
KHV | Хабаровск
(3 rows)
72 To understand how it works, take a look at the aircrafts or
v airports definition using the \d+ psql command.
Simple Queries
SELECT t.passenger_name,
b.book_date
FROM bookings b
JOIN tickets t
ON t.book_ref = b.book_ref
JOIN boarding_passes bp
ON bp.ticket_no = t.ticket_no
JOIN flights f
ON f.flight_id = bp.flight_id
WHERE f.departure_airport = 'SVO'
AND f.arrival_airport = 'OVB'
AND f.scheduled_departure::date =
bookings.now()::date - INTERVAL '2 day'
AND bp.seat_no = '1A';
SELECT count(*)
FROM flights f
JOIN seats s
ON s.aircraft_code = f.aircraft_code
WHERE f.flight_no = 'PG0404'
AND f.scheduled_departure::date =
bookings.now()::date - INTERVAL '1 day'
AND NOT EXISTS (
SELECT NULL
FROM boarding_passes bp
WHERE bp.flight_id = f.flight_id
AND bp.seat_no = s.seat_no
);
SELECT count(*)
FROM ( SELECT s.seat_no
FROM seats s
WHERE s.aircraft_code = (
SELECT aircraft_code
FROM flights
WHERE flight_no = 'PG0404'
AND scheduled_departure::date =
bookings.now()::date - INTERVAL '1 day'
)
EXCEPT
SELECT bp.seat_no
FROM boarding_passes bp
WHERE bp.flight_id = (
SELECT flight_id
FROM flights
WHERE flight_no = 'PG0404'
AND scheduled_departure::date =
bookings.now()::date - INTERVAL '1 day'
)
) t;
74 The choice largely depends on your personal preferences.
v You only have to take into account that query execution will
differ, so if performance is important, it makes sense to try
both approaches.
Problem. Which flights had the longest delays? Print the list
of ten “leaders.”
SELECT f.flight_no,
f.scheduled_departure,
f.actual_departure,
f.actual_departure - f.scheduled_departure
AS delay
FROM flights f
WHERE f.actual_departure IS NOT NULL
ORDER BY f.actual_departure - f.scheduled_departure
DESC
LIMIT 10;
You can define the same condition using the status col-
umn by listing all the applicable statuses. Or you can skip
the WHERE condition altogether by specifying the DESC NULLS
LAST sorting order, so that undefined values are returned at
the end of the selection.
Aggregate Functions
SELECT f.flight_no,
f.scheduled_duration,
min(f.actual_duration),
max(f.actual_duration),
sum(CASE
WHEN f.actual_departure >
f.scheduled_departure +
INTERVAL '1 hour'
THEN 1 ELSE 0
END) delays
FROM flights_v f
WHERE f.departure_city = 'Moscow'
AND f.arrival_city = 'St. Petersburg'
AND f.status = 'Arrived'
GROUP BY f.flight_no,
f.scheduled_duration;
Solution. Use the fact that boarding pass numbers are issued
in the check-in order.
SELECT t.passenger_name,
t.ticket_no
FROM tickets t
JOIN boarding_passes bp
ON bp.ticket_no = t.ticket_no
GROUP BY t.passenger_name,
t.ticket_no
HAVING max(bp.boarding_no) = 1
AND count(*) > 1;
76 Problem. How many people can be included into a single
v booking according to the available data?
SELECT tt.cnt,
count(*)
FROM (
SELECT t.book_ref,
count(*) cnt
FROM tickets t
GROUP BY t.book_ref
) tt
GROUP BY tt.cnt
ORDER BY tt.cnt;
Window Functions
Problem. For each ticket, display all the included flight seg-
ments, together with connection time. Limit the result to the
tickets booked a week ago.
In the query results provided below, we can see that the time
cushion between flights is several days in some cases. As a
rule, these are round-trip tickets, that is, we see the time of
the stay in the point of destination, not the time between con-
necting flights. Using the solution for one of the problems in
the “Arrays” section, you can take this fact into account when
building the query.
SELECT tf.ticket_no, 77
f.departure_airport, v
f.arrival_airport,
f.scheduled_arrival,
lead(f.scheduled_departure) OVER w
AS next_departure,
lead(f.scheduled_departure) OVER w -
f.scheduled_arrival AS gap
FROM bookings b
JOIN tickets t
ON t.book_ref = b.book_ref
JOIN ticket_flights tf
ON tf.ticket_no = t.ticket_no
JOIN flights f
ON tf.flight_id = f.flight_id
WHERE b.book_date =
bookings.now()::date - INTERVAL '7 day'
WINDOW w AS (PARTITION BY tf.ticket_no
ORDER BY f.scheduled_departure);
SELECT passenger_name,
round( 100.0 * cnt / sum(cnt) OVER (), 2)
AS percent
FROM (
SELECT passenger_name,
count(*) cnt
FROM tickets
GROUP BY passenger_name
) t
ORDER BY percent DESC;
78 Problem. Solve the previous problem for first names and last
v names separately.
WITH p AS (
SELECT left(passenger_name,
position(' ' IN passenger_name))
AS passenger_name
FROM tickets
)
SELECT passenger_name,
round( 100.0 * cnt / sum(cnt) OVER (), 2)
AS percent
FROM (
SELECT passenger_name,
count(*) cnt
FROM p
GROUP BY passenger_name
) t
ORDER BY percent DESC;
Arrays
WITH t AS (
SELECT ticket_no,
a,
a[1] departure,
a[cardinality(a)] last_arrival,
a[cardinality(a)/2+1] middle
FROM (
SELECT t.ticket_no,
array_agg( f.departure_airport
ORDER BY f.scheduled_departure) ||
(array_agg( f.arrival_airport
ORDER BY f.scheduled_departure DESC)
)[1] AS a
FROM tickets t
JOIN ticket_flights tf
ON tf.ticket_no = t.ticket_no
JOIN flights f
ON f.flight_id = tf.flight_id
GROUP BY t.ticket_no
) t
)
SELECT t.ticket_no,
t.a,
t.departure,
CASE
WHEN t.departure = t.last_arrival
THEN t.middle
ELSE t.last_arrival
END arrival,
(t.departure = t.last_arrival) return_ticket
FROM t;
80 In this example, the tickets table is scanned only once. The
v array of airports is displayed for clarity; for large volumes of
data, it makes sense to remove it from the query since extra
data can hamper performance.
SELECT r1.departure_airport,
r1.arrival_airport,
r1.days_of_week dow,
r2.days_of_week dow_back
FROM routes r1
JOIN routes r2
ON r1.arrival_airport = r2.departure_airport
AND r1.departure_airport = r2.arrival_airport
WHERE NOT (r1.days_of_week && r2.days_of_week);
Recursive Queries
Solution. Here you have to find the shortest path in the graph.
It can be done with the following recursive query:
WITH RECURSIVE p( 81
last_arrival, v
destination,
hops,
flights,
flight_time,
found
) AS (
SELECT a_from.airport_code,
a_to.airport_code,
array[a_from.airport_code],
array[]::char(6)[],
interval '0',
a_from.airport_code = a_to.airport_code
FROM airports a_from,
airports a_to
WHERE a_from.airport_code = 'UKX'
AND a_to.airport_code = 'CNN'
UNION ALL
SELECT r.arrival_airport,
p.destination,
(p.hops || r.arrival_airport)::char(3)[],
(p.flights || r.flight_no)::char(6)[],
p.flight_time + r.duration,
bool_or(r.arrival_airport = p.destination)
OVER ()
FROM p
JOIN routes r
ON r.departure_airport = p.last_arrival
WHERE NOT r.arrival_airport = ANY(p.hops)
AND NOT p.found
)
SELECT hops,
flights,
flight_time
FROM p
WHERE p.last_arrival = p.destination;
Solution. We can take the previous query as the basis for the
solution. However, the first iteration must now contain all
possible airport pairs, not a single pair: each airport must be
connected to all other airports. For all these pairs of airports
we first find the shortest path, and then select the longest of
them.
This query also uses the found attribute, but here it should
be calculated separately for each pair of airports.
WITH RECURSIVE p( 83
departure, v
last_arrival,
destination,
hops,
found
) AS (
SELECT a_from.airport_code,
a_from.airport_code,
a_to.airport_code,
array[a_from.airport_code],
a_from.airport_code = a_to.airport_code
FROM airports a_from,
airports a_to
UNION ALL
SELECT p.departure,
r.arrival_airport,
p.destination,
(p.hops || r.arrival_airport)::char(3)[],
bool_or(r.arrival_airport = p.destination)
OVER (PARTITION BY p.departure,
p.destination)
FROM p
JOIN routes r
ON r.departure_airport = p.last_arrival
WHERE NOT r.arrival_airport = ANY(p.hops)
AND NOT p.found
)
SELECT max(cardinality(hops)-1)
FROM p
WHERE p.last_arrival = p.destination;
WITH RECURSIVE p(
last_arrival,
destination,
hops,
flights,
flight_time,
min_time
) AS (
SELECT a_from.airport_code,
a_to.airport_code,
array[a_from.airport_code],
array[]::char(6)[],
interval '0',
NULL::interval
FROM airports a_from,
airports a_to
WHERE a_from.airport_code = 'UKX'
AND a_to.airport_code = 'CNN'
UNION ALL
SELECT r.arrival_airport,
p.destination,
(p.hops || r.arrival_airport)::char(3)[],
(p.flights || r.flight_no)::char(6)[],
p.flight_time + r.duration,
least(
p.min_time, min(p.flight_time+r.duration)
FILTER (
WHERE r.arrival_airport = p.destination
) OVER ()
)
FROM p
JOIN routes r
ON r.departure_airport = p.last_arrival
WHERE NOT r.arrival_airport = ANY(p.hops)
AND p.flight_time + r.duration <
coalesce(p.min_time, INTERVAL '1 year')
)
SELECT hops, 85
flights, v
flight_time
FROM (
SELECT hops,
flights,
flight_time,
min(min_time) OVER () min_time
FROM p
WHERE p.last_arrival = p.destination
) t
WHERE flight_time = min_time;
VI PostgreSQL
for Applications
A Separate User
Note that the database name is not the only thing that has
changed in the prompt: instead of the hash symbol (#), the
greater than sign is displayed (>). The hash symbol indicates
the superuser rights, similar to the root user in Unix.
The app user works with their database without any restric-
tions. For example, this user can create a table:
Remote Connections
In our example, both the client and the database are located
on the same system. Clearly, you can install PostgreSQL onto
a separate server and connect to it from a different system
(for example, from an application server). In this case, you
must specify your database server address instead of local-
host. But it is not enough: for security reasons, PostgreSQL
only allows local connections by default.
#listen_addresses = 'localhost'
listen_addresses = '*'
For our purposes, you have to add the following line at the
end of the pg_hba.conf file, so that the app user can access
the appdb database from any address if the correct password
is entered:
You can install PHP for Windows from the PHP website:
windows.php.net/download. The extension for PostgreSQL
is already included into the binary distribution, but you must
find and uncomment (by removing the semicolon) the follow-
ing line in the php.ini file:
;extension=php_pgsql.dll
<?php
$conn = pg_connect('host=localhost port=5432 ' .
'dbname=appdb user=app ' .
'password=p@ssw0rd') or die;
$query = pg_query('SELECT * FROM greeting') or die;
while ($row = pg_fetch_array($query)) {
echo $row[0].PHP_EOL;
}
pg_free_result($query);
pg_close($conn);
?>
$ php test.php
Hello, world!
There are several Perl builds for Windows, which are listed
at www.perl.org/get.html. Popular builds of ActiveState Perl
and Strawberry Perl already include the driver required for
PostgreSQL.
use DBI;
my $conn = DBI->connect(
'dbi:Pg:dbname=appdb;host=localhost;port=5432',
'app','p@ssw0rd') or die;
my $query = $conn->prepare('SELECT * FROM greeting');
$query->execute() or die;
while (my @row = $query->fetchrow_array()) {
print @row[0]."\n";
}
$query->finish();
$conn->disconnect();
$ perl test.pl
Hello, world!
import psycopg2
conn = psycopg2.connect(
host='localhost', port='5432', database='appdb',
user='app', password='p@ssw0rd')
cur = conn.cursor()
cur.execute('SELECT * FROM greeting')
rows = cur.fetchall()
for row in rows:
print row[0]
conn.close()
$ python test.py
Hello, world!
Java 95
vi
In Java, database operation is implemented via the JDBC in-
terface. Install JDK 1.7; a package with the JDBC driver is also
required:
import java.sql.*;
public class Test {
public static void main(String[] args)
throws SQLException {
Connection conn = DriverManager.getConnection(
"jdbc:postgresql://localhost:5432/appdb",
"app", "p@ssw0rd");
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(
"SELECT * FROM greeting");
while (rs.next()) {
System.out.println(rs.getString(1));
}
rs.close();
st.close();
conn.close();
}
}
Backup
Although our database contains only one table, it’s still worth
taking care of data persistence. While your application has
little data, the easiest way to create a backup is to use the
pg_dump utility:
$ createdb appdb2
$ psql -d appdb2 -f appdb.dump
$ pg_basebackup -D backup
Here we’ll only cover some of the basic settings that must
be considered for production-level database system. Fine-
tuning for a particular application requires additional knowl-
edge, which you can get, for example, in PostgreSQL database
administration courses (see p. 147).
shared_buffers = '8GB'
effective_cache_size = '24GB'
work_mem = '128MB'
maintenance_work_mem = '512MB'
random_page_cost = 1.2
Connection Settings
Bad Advice
Configuration Parameters
In configuration settings
of the 1C information
database, specify the
IP-address and port of
the PostgreSQL server
as your database server
and choose “PostgreSQL”
as the required DBMS
type. Specify the name
of the database that will
be used for 1C and select
the “Create database
if none present” check
box (never create this
database using Post-
greSQL means). Provide
108 the name and password of a superuser role that will be used
vii for connections.
Installation
Connecting to a Server
If you don’t want to enter the password every time, select the
Save password check box. Passwords are encrypted using a
master password, which you are prompted to enter when you
start pgAdmin for the first time.
Note that this user must already have a password. For exam-
ple, for the postgres user, you can do it with the following
command:
When you click the Save button, the application checks that
the server with the specified parameters is available, and
registers a new connection.
Browser
In the left pane, you can see the Browser tree. As you expand
its objects, you can get to the server, which we have called
LOCAL. You can see all the databases it contains:
If you expand the Schemas item for the appdb database, you
can find the greetings table that we have created, view its
columns, integrity constraints, indexes, triggers, etc.
For each object type, the context (right-click) menu lists all
the possible actions, such as export to a file or load from a
file, assign privileges, delete.
Running Queries
Enter your query in the upper part of the window and press
F5. The Data Output tab in the lower part of the window will
display the result of the query.
You can type the next query starting from a new line, with-
out deleting the previous query: just select the required code
fragment before pressing F5. Thus, the whole history of your
114 actions will be always in front of you. It is usually more con-
viii venient than searching for the required query in the log on
the Query History tab.
Other Features
will return the row from chapter II (but not from chapter I,
where the adjective “fascinating” is used):
-[ RECORD 1 ]-----------------------------------------
txt | Getting more fascinated with the world of
databases
The {0.1, 0.0, 1.0, 0.0} array sets the weight. It is an optional
argument of the ts_rank_cd function. By default, array {0.1,
0.2, 0.4, 1.0} corresponds to D, C, B, A. The word’s weight affects
ranking of the returned row.
Once the initial shock had passed, it became clear that for
most real tasks such a simple structure was not enough.
Composite keys were introduced, and then groups of keys
appeared. Relational database systems didn’t want to fall be-
hind and started adding new features that were common in
NoSQL.
We can see that the two entries are related to merits of Anna
and Nina, but such a result is unlikely to satisfy us as Anna’s
merits are actually “none.” Let’s modify the query:
Make sure that this query only returns Nina, whose merits are
real.
However, this method does not always work. Let’s try to find 127
out which guitars our musician Victor plays: ix
name | Victor
details | { "hobbies": +
| { "guitarist": +
| { "band": "Postgressors", +
| "guitars":["Strat","Telec"] +
| } +
| } +
| }
To get to guitars, let’s use the #> operator and go down the
hierarchy, starting with “hobbies”:
For example, let’s find the entry that mentions Lucie, a moth-
er-of-five’s daughter:
To learn more about json and jsonb types and the functions
that can be used with them, see PostgreSQL documentation
at postgrespro.com/doc/datatype-json and postgrespro.com/
doc/functions-json.
Using this query language, you can, for example, search for
data by path. The dot notation represents the hierarchy in-
side jsonb:
test=# SELECT * 131
FROM student_details ix
WHERE details::jsonb @@
'hobbies.guitarist.band=Postgressors'::jsquery;
But it’s still very hard to work with the required value without
knowing the hierarchy.
The queries can use two hierarchies in search: one inside the
path expression, which defines the search area, and the other
inside the filter expression, which matches the results with
the specified condition. It means there are different ways to
reach the same goal.
For example, the query 133
ix
test=# SELECT s_id, jsonb_path_query(
details::jsonb,
'$.hobbies.guitarist.band?(@=="Postgressors")'
)
FROM student_details;
s_id | jsonb_path_query
------+------------------
1432 | "Postgressors"
(1 row)
In the real world, applications are not isolated, and they often
have to send data between each other. Such interaction can
be implemented at the application level, for example, with
the help of web services or file exchange, or you can use the
database functionality for this purpose.
Installing Extensions
Foreign data wrappers for Oracle, MySQL, and SQL Server are
available as extensions:
1. Oracle: github.com/laurenz/oracle_fdw
2. MySQL: github.com/EnterpriseDB/mysql_fdw
Oracle
MySQL
Just like the Oracle wrapper, mysql_fdw allows both read and
write operations.
SQL Server 141
ix
Create an extension for the required foreign data wrapper:
You can display the list of imported tables using the \det
command, or find them in the system catalog by running the
following query:
X Education
and Certification
Documentation
Training Courses
Duration: 3 days
Architecture
4. PostgreSQL general overview
5. Isolation and multi-version concurrency control
6. Buffer cache and write-ahead log
Data management
7. Databases and schemas
8. System catalog
9. Tablespaces
10. Low-level details
Administration tasks
11. Monitoring
12. Maintenance
Access control
13. Roles and attributes
14. Privileges
15. Row-level security
16. Connection and authentication
Backups
17. Overview
Replication
18. Overview
SQL fundamentals.
Good command of Unix OS.
Familiarity with PostgreSQL within the scope of the DBA1
course.
Topics:
Logging
8. Buffer cache
9. Write-ahead log
10. Checkpoints
11. WAL configuration
152 Locking
x 12. Object locks
13. Row-level locks
14. Memory locks
Administration tasks
15. Managing extensions
16. Localization
17. Server upgrades
Duration: 2 days
SQL fundamentals.
Good command of Unix OS.
Familiarity with PostgreSQL within the scope of the DBA1
course.
Taking backups.
Setting up physical and logical replication.
Recognizing replication use cases.
Understanding clusterization.
Topics: 153
x
Backups
1. Logical backup
2. Base backup
3. WAL archive
Replication
4. Physical replication
5. Switchover to a replica
6. Logical replication
7. Usage scenarios
Clusterization
8. Overview
Duration: 4 days
SQL fundamentals.
Experience with any procedural programming language.
Basic knowledge of Unix OS.
154 Knowledge and skills gained:
x
General information about PostgreSQL architecture.
Using the main database objects.
Programming in SQL and PL/pgSQL on the server side.
Using the main data types, including records and arrays.
Setting up client-server communication channels.
Topics:
Basic toolkit
1. Installation and server management, psql
Architecture
2. PostgreSQL general overview
3. Isolation and multi-version concurrency control
4. Buffer cache and write-ahead log
Data management
5. Logical structure
6. Physical structure
“Bookstore” application
7. Data model of the application
8. Client-server interaction
SQL
9. Functions
10. Composite types
PL/pgSQL
11. Language overview and programming structures
12. Executing queries
13. Cursors 155
14. Dynamic SQL x
15. Arrays
16. Error handling
17. Triggers
18. Debugging
Access control
19. Overview
Duration: 2 days
Professional Certification
• PostgreSQL internals.
• Server setup and monitoring, database maintenance
tasks.
• Performance optimization tasks, query tuning.
• Taking backups.
• Physical and logical replication setup for various usage
scenarios.
While taking the test, you can refer to course materials and
PostgreSQL documentation, but using any other sources of
information is prohibited.
Contents:
Introduction.
Configuring the environ-
ment.
Basic operations.
Data types.
DDL fundamentals.
Queries.
Data manipulation.
Indexes.
Transactions.
Performance tuning.
E. Morgunov
PostgreSQL. SQL Basics: textbook / E.Morgunov; edited by
E. Rogov, P. Luzanov. — SPb.: BHV-Petersburg, 2018. — 336 pp.
ISBN 978-5-9775-4022-3 (printed edition)
ISBN 978-5-6041193-2-7 (electronic edition)
You can download a soft copy of this book from postgrespro. 161
ru/education/books/sqlprimer. x
B. Novikov
Database Technology Fundamentals: textbook / B. Novikov,
E. Gorshkova, N. Grafeeva; edited by E. Rogov. — 2nd edition —
M.: DMK Press, 2020. — 582 pp.
ISBN 978-5-97060-841-8 (printed edition)
ISBN 978-5-6041193-5-8 (electronic edition)
Contents: 163
x
Part I. From Theory to Practice
Introduction.
Some database theory.
Getting started with databases.
Introduction to SQL.
Database access management.
Transactions and data consistency.
Database application development.
Relational model extensions.
Various types of database systems.
Mailing Lists
Thus, you can stay informed about new features already in-
cluded into PostgreSQL or planned for the next release.
Conferences
Contact information:
Both Postgres Pro versions have been extended with the re-
quired information security functionality and are certified by
FSTEC (Federal Service for Technical and Export Control).
Postgres Training
postgrespro.com/education/books/introbook
© PPG, 2016–2020
ISBN 978-5-6041193-7-2