මිණුම් ලකුණ
පෝස්ට්ග්රෙස් 9.4 සහ 9.5 සමඟ වඩාත් සිත්ගන්නාසුලු අපේක්ෂකයින් පරීක්ෂා කිරීම, අඩක් යථාර්ථවාදී වගුවක් සහිත පේළි 200 ක පේළි 200 ක් purchases
සහ 10k එකිනෙකට වෙනස්customer_id
( පාරිභෝගිකයෙකුට පේළි 20 ක් ).
Postgres 9.5 සඳහා මම සුවිශේෂී ගනුදෙනුකරුවන් 86446 ක් සමඟ 2 වන පරීක්ෂණය පැවැත්වුවෙමි. පහත බලන්න ( එක් ගනුදෙනුකරුවකුට සාමාන්ය පේළි 2.3 ).
පිහිටුවීම
ප්රධාන වගුව
CREATE TABLE purchases (
id serial
, customer_id int -- REFERENCES customer
, total int -- could be amount of money in Cent
, some_column text -- to make the row bigger, more realistic
);
මම භාවිතා කරන්නේ a serial
customer_id
වඩාත් සාමාන්ය සැකසුමක් බැවින් (පහත එකතු කරන ලද PK අවහිරතා) සහ පූර්ණ සංඛ්යාවක් . some_column
සාමාන්යයෙන් තවත් තීරු සෑදීම සඳහා එකතු කරන ලදි.
ව්යාජ දත්ත, පී.කේ., දර්ශකය - සාමාන්ය වගුවක මිය ගිය ටුපල් කිහිපයක් ද ඇත:
INSERT INTO purchases (customer_id, total, some_column) -- insert 200k rows
SELECT (random() * 10000)::int AS customer_id -- 10k customers
, (random() * random() * 100000)::int AS total
, 'note: ' || repeat('x', (random()^2 * random() * random() * 500)::int)
FROM generate_series(1,200000) g;
ALTER TABLE purchases ADD CONSTRAINT purchases_id_pkey PRIMARY KEY (id);
DELETE FROM purchases WHERE random() > 0.9; -- some dead rows
INSERT INTO purchases (customer_id, total, some_column)
SELECT (random() * 10000)::int AS customer_id -- 10k customers
, (random() * random() * 100000)::int AS total
, 'note: ' || repeat('x', (random()^2 * random() * random() * 500)::int)
FROM generate_series(1,20000) g; -- add 20k to make it ~ 200k
CREATE INDEX purchases_3c_idx ON purchases (customer_id, total DESC, id);
VACUUM ANALYZE purchases;
customer
වගුව - උසස් විමසුම සඳහා
CREATE TABLE customer AS
SELECT customer_id, 'customer_' || customer_id AS customer
FROM purchases
GROUP BY 1
ORDER BY 1;
ALTER TABLE customer ADD CONSTRAINT customer_customer_id_pkey PRIMARY KEY (customer_id);
VACUUM ANALYZE customer;
9.5 සඳහා මගේ දෙවන පරීක්ෂණයෙහිදී මම එකම සැකසුම භාවිතා කළෙමි, නමුත් random() * 100000
උත්පාදනය සඳහාcustomer_id
කිරීම සඳහා පේළි කිහිපයක් පමණක් ලබා ගැනීමට customer_id
.
වගුව සඳහා වස්තු ප්රමාණ purchases
මෙම විමසුම සමඟ ජනනය කරන ලදි .
what | bytes/ct | bytes_pretty | bytes_per_row
-----------------------------------+----------+--------------+---------------
core_relation_size | 20496384 | 20 MB | 102
visibility_map | 0 | 0 bytes | 0
free_space_map | 24576 | 24 kB | 0
table_size_incl_toast | 20529152 | 20 MB | 102
indexes_size | 10977280 | 10 MB | 54
total_size_incl_toast_and_indexes | 31506432 | 30 MB | 157
live_rows_in_text_representation | 13729802 | 13 MB | 68
------------------------------ | | |
row_count | 200045 | |
live_tuples | 200045 | |
dead_tuples | 19955 | |
විමසුම්
WITH cte AS (
SELECT id, customer_id, total
, row_number() OVER(PARTITION BY customer_id ORDER BY total DESC) AS rn
FROM purchases
)
SELECT id, customer_id, total
FROM cte
WHERE rn = 1;
2. row_number()
උපවගන්තියේ (මගේ ප්රශස්තිකරණය)
SELECT id, customer_id, total
FROM (
SELECT id, customer_id, total
, row_number() OVER(PARTITION BY customer_id ORDER BY total DESC) AS rn
FROM purchases
) sub
WHERE rn = 1;
SELECT DISTINCT ON (customer_id)
id, customer_id, total
FROM purchases
ORDER BY customer_id, total DESC, id;
4. උපසිරැසි සමඟ rCTE LATERAL
( මෙහි බලන්න )
WITH RECURSIVE cte AS (
( -- parentheses required
SELECT id, customer_id, total
FROM purchases
ORDER BY customer_id, total DESC
LIMIT 1
)
UNION ALL
SELECT u.*
FROM cte c
, LATERAL (
SELECT id, customer_id, total
FROM purchases
WHERE customer_id > c.customer_id -- lateral reference
ORDER BY customer_id, total DESC
LIMIT 1
) u
)
SELECT id, customer_id, total
FROM cte
ORDER BY customer_id;
5. customer
සමඟ වගුව LATERAL
( මෙහි බලන්න )
SELECT l.*
FROM customer c
, LATERAL (
SELECT id, customer_id, total
FROM purchases
WHERE customer_id = c.customer_id -- lateral reference
ORDER BY total DESC
LIMIT 1
) l;
SELECT (array_agg(id ORDER BY total DESC))[1] AS id
, customer_id
, max(total) AS total
FROM purchases
GROUP BY customer_id;
ප්රතිපල
ඉහත විමසුම් සඳහා ක්රියාත්මක කිරීමේ කාලය EXPLAIN ANALYZE
(සහ සියලු විකල්ප අක්රීයයි ), ලකුණු 5 න් හොඳම .
සියලුම විමසුම් මඟින් දර්ශක පමණක් පරිලෝකනය කර ඇත purchases2_3c_idx
(වෙනත් පියවර අතර). ඒවායින් සමහරක් දර්ශකයේ කුඩා ප්රමාණයට පමණක් වන අතර අනෙක් ඒවා වඩාත් .ලදායී වේ.
A. පෝස්ට්ග්රෙස් 9.4 පේළි 200 ක් සහ ඩොලර් 20 බැගින් customer_id
1. 273.274 ms
2. 194.572 ms
3. 111.067 ms
4. 92.922 ms
5. 37.679 ms -- winner
6. 189.495 ms
B. Postgres 9.5 ට සමාන වේ
1. 288.006 ms
2. 223.032 ms
3. 107.074 ms
4. 78.032 ms
5. 33.944 ms -- winner
6. 211.540 ms
C. B. ට සමාන නමුත් පේළි 2.3 බැගින් customer_id
1. 381.573 ms
2. 311.976 ms
3. 124.074 ms -- winner
4. 710.631 ms
5. 311.976 ms
6. 421.679 ms
අදාළ මිණුම් සලකුණු
මෙන්න සමඟ පරීක්ෂා "ogr" විසින් නව එකක් 10M පේළි හා සුවිශේෂී "පාරිභෝගිකයන්" 60k මත Postgres 11.5 (2019 සැප්තැම්බර් වන විට වත්මන්). ප්රති results ල තවමත් අප දැක ඇති දේට අනුකූල වේ:
2011 සිට මුල් (යල් පැන ගිය) මිණුම් ලකුණ
මම පෝස්ට්ග්රෙස්කියුඑල් 9.1 සමඟ පරීක්ෂණ 3 ක් සැබෑ ජීවිත වගුවක පේළි 65579 ක් හා එක් තීරු තුනක තනි තීරු බීට්රී දර්ශක මත ධාවනය කර ඇති අතර හොඳම ක්රියාත්මක කිරීමේ කාලය ලකුණු 5 කි. GOMGPonies හි පළමු විමසුම ( ) ඉහත විසඳුම
සමඟ සංසන්දනය කිරීම ( ):A
DISTINCT ON
B
සම්පූර්ණ වගුව තෝරන්න, මෙම නඩුවේ පේළි 5958 ක් ලැබේ.
A: 567.218 ms
B: 386.673 ms
WHERE customer BETWEEN x AND y
පේළි 1000 ක් ඇති වන කොන්දේසිය භාවිතා කරන්න .
A: 249.136 ms
B: 55.111 ms
සමඟ තනි පාරිභෝගිකයෙකු තෝරන්න WHERE customer = x
.
A: 0.143 ms
B: 0.072 ms
අනෙක් පිළිතුරෙහි විස්තර කර ඇති දර්ශකය සමඟ එකම පරීක්ෂණය නැවත නැවතත්
CREATE INDEX purchases_3c_idx ON purchases (customer, total DESC, id);
1A: 277.953 ms
1B: 193.547 ms
2A: 249.796 ms -- special index not used
2B: 28.679 ms
3A: 0.120 ms
3B: 0.048 ms
MAX(total)
?