geometry
ডাব্লুজিএস 1984 ভৌগলিক ডেটা (এসআরআইডি 4326) ব্যবহার করে কলামগুলির সাথে বড় টেবিলগুলির সাথে ভাল জিওডেটিক কোয়েরি পারফরম্যান্স পাওয়ার দুটি কী রয়েছে :
- ব্যবহার
ST_DWithin
ফাংশনটি যা কোনও উপলভ্য স্থানিক সূচক ব্যবহার করে অনুসন্ধান করে এবং কার্টেসিয়ান দূরত্ব সহ ভৌগলিক বৈশিষ্ট্যগুলি সন্ধান করবে
- ভূগোলের কাস্টে একটি অতিরিক্ত সূচক তৈরি করুন, তাই
ST_DWithin
এটি ব্যবহার করতে পারেন
আসুন আসুন দেখুন আসল বিশ্বে কী ঘটে। প্রথমে আমাদের দশ মিলিয়ন এলোমেলো পয়েন্টের একটি সারণী তৈরি এবং তৈরি করা দরকার:
DROP TABLE IF EXISTS example1
;
CREATE TABLE example1 (
idcol serial NOT NULL,
geomcol geometry NULL,
CONSTRAINT example1_pk PRIMARY KEY (idcol),
CONSTRAINT enforce_srid CHECK (st_srid(geomcol) = 4326)
)
with (
OIDS=FALSE
);
INSERT INTO example1(geomcol)
SELECT ST_SetSRID(
ST_MakePoint(
(random()*360.0) - 180.0,
(acos(1.0 - 2.0 * random()) * 2.0 - pi()) * 90.0 / pi()),
4326) as geomcol
FROM generate_series(1, 1000000) vtab;
CREATE INDEX example1_spx ON example1 USING GIST (geomcol);
-- (took about 22 sec)
যদি আমরা ST_Distance কোয়েরি কার্যকর করি, আমরা আপনার প্রত্যাশিত পূর্ণ টেবিল স্ক্যানটি পেয়েছি:
EXPLAIN ANALYZE VERBOSE
SELECT count(*)
FROM example1
WHERE ST_Distance(geomcol::geography,ST_SetSRID(ST_MakePoint(6.9333,46.8167),4326)::geography) < 30 * 1609.34
;
Aggregate (cost=274167.33..274167.34 rows=1 width=0) (actual time=4940.531..4940.532 rows=1 loops=1)
Output: count(*)
-> Seq Scan on bob.example1 (cost=0.00..273334.00 rows=333333 width=0) (actual time=592.766..4940.509 rows=11 loops=1)
Output: idcol, geomcol
Filter: (_st_distance((example1.geomcol)::geography, '0101000020E61000005D6DC5FEB2BB1B40545227A089684740'::geography, 0::double precision, true) < 48280.2::double precision)
Rows Removed by Filter: 999989
Planning time: 2.137 ms
Execution time: 4940.568 ms
এখন, আমরা যদি ব্যবহার ST_DWithin
করি তবে আমরা এখনও একটি পূর্ণ টেবিল স্ক্যান পাই (তত দ্রুত হলেও):
EXPLAIN ANALYZE VERBOSE
SELECT count(*)
FROM example1
WHERE ST_DWithin(geomcol::geography,ST_SetSRID(ST_MakePoint(6.9333,46.8167),4326)::geography,30 * 1609.34)
;
Aggregate (cost=405867.33..405867.34 rows=1 width=0) (actual time=908.716..908.716 rows=1 loops=1)
Output: count(*)
-> Seq Scan on bob.example1 (cost=0.00..405834.00 rows=13333 width=0) (actual time=38.449..908.700 rows=7 loops=1)
Output: idcol, geomcol
Filter: (((example1.geomcol)::geography && '0101000020E61000005D6DC5FEB2BB1B40545227A089684740'::geography) AND ('0101000020E61000005D6DC5FEB2BB1B40545227A089684740'::geography && _st_expand((example1.geomcol)::geography, 48280.2::double precision) (...)
Rows Removed by Filter: 999993
Planning time: 2.017 ms
Execution time: 908.763 ms
এবং এটিই শেষ টুকরো - প্রচ্ছদ সূচক তৈরি করা (কাস্ট ভূগোল):
CREATE INDEX example1_gpx ON example1 USING GIST (geography(geomcol));
-- (Takes an extra 13 sec)
EXPLAIN ANALYZE VERBOSE
SELECT count(*)
FROM example1
WHERE ST_DWithin(geomcol::geography,ST_SetSRID(ST_MakePoint(6.9333,46.8167),4326)::geography,30 * 1609.34)
;
Aggregate (cost=96538.95..96538.96 rows=1 width=0) (actual time=0.775..0.775 rows=1 loops=1)
Output: count(*)
-> Bitmap Heap Scan on bob.example1 (cost=8671.62..96505.62 rows=13333 width=0) (actual time=0.586..0.769 rows=19 loops=1)
Output: idcol, geomcol
Recheck Cond: ((example1.geomcol)::geography && '0101000020E61000005D6DC5FEB2BB1B40545227A089684740'::geography)
Filter: (('0101000020E61000005D6DC5FEB2BB1B40545227A089684740'::geography && _st_expand((example1.geomcol)::geography, 48280.2::double precision)) AND _st_dwithin((example1.geomcol)::geography, '0101000020E61000005D6DC5FEB2BB1B40545227A089684740':: (...)
Rows Removed by Filter: 14
Heap Blocks: exact=33
-> Bitmap Index Scan on example1_gpx (cost=0.00..8668.29 rows=200000 width=0) (actual time=0.384..0.384 rows=33 loops=1)
Index Cond: ((example1.geomcol)::geography && '0101000020E61000005D6DC5FEB2BB1B40545227A089684740'::geography)
Planning time: 2.572 ms
Execution time: 0.820 ms
অবশেষে, অপ্টিমাইজারটি স্থানিক সূচকটি ব্যবহার করছে, এবং এটি দেখায়, তবে বন্ধুদের মধ্যে তিনটি ক্রমের পরিমাণ কী?
কিছু সতর্কতা:
আমি একটি ডাটাবেস নার্ড, তাই আমার বাড়ির পিসি ডাটাবেস ডিফল্ট টেবিল স্পেসের জন্য 16 গিগাবাইট র্যাম, ছয় 3.3 গিগাহার্টজ কোর এবং একটি 256 জিবি এসএসডি পেয়েছে; আপনার মাইলেজ পরিবর্তিত হতে পারে
ক্যাশে "গরম" পৃষ্ঠাগুলি সম্পর্কে শ্রদ্ধার সাথে খেলার ক্ষেত্রটি সমতল করতে আমি প্রতিটি ক্যোয়ারির আগে সৃষ্টি এসকিউএল পুনরায় চালিত করেছি, তবে এটি কিছুটা ভিন্ন ফলাফল আনতে পারে কারণ একই র্যান্ডম বীজ বিভিন্ন রানের জন্য ব্যবহার করা হয়নি
এবং একটি নোট:
- আমি সমান-অঞ্চল বিতরণের জন্য আর্ক-কোসাইন ব্যবহার করতে মূল {-90, + 90} অক্ষাংশের পরিসীমাটি চিহ্নিত করেছি (খুঁটির দিকে কম পক্ষপাতিত্বশীল)
ST_SetSRID()
থেকেST_MakePoint
ক্যোয়ারীতে ভূগোল এ কাস্ট আগে।