কীভাবে দক্ষতার সাথে ডেটলাইনটির সবচেয়ে কাছের পয়েন্টটি খুঁজে পাবেন?


10

আমার পোস্টগ্রিজ এসকিউএল 9.1 টেবিল রয়েছে কয়েক হাজার পোস্টজিআইএস পয়েন্ট সহ। এগুলির প্রত্যেকের জন্য আমি পয়েন্টের অন্য সারণির নিকটতম পয়েন্টটি খুঁজতে চাই। দ্বিতীয় সারণীর পয়েন্টগুলি পুরো বিশ্ব জুড়ে গ্রিডকে উপস্থাপন করে, তাই আমি জানি যে সর্বদা 1 ডিগ্রির মধ্যে একটি ম্যাচ হতে চলেছে। এটি আমি এখন অবধি যে কোয়েরিটি ব্যবহার করছি, এটি জিআইএসটি সূচকগুলি ব্যবহার করে, তাই এটি যুক্তিযুক্তভাবে দ্রুত (মোটামুটি 30 সেকেন্ড)।

SELECT DISTINCT ON (p.id)
    p.id, ST_AsText(p.pos)
    , ST_AsText(first_value(g.location) OVER (PARTITION BY p.id ORDER BY ST_Distance(p.pos, g.location::geography)))
FROM point p
JOIN grid g ON ST_DWithin(p.pos::geometry, g.location, 1)

একমাত্র সমস্যা ডেটলাইন। গ্রিড পয়েন্টগুলির মধ্যে কেবল অক্ষাংশ 180 রয়েছে, -180 নয়। ST_Distance এর জ্যামিতি সংস্করণটি ব্যবহার করার সময় এটি ডেটলাইনটির অন্য দিকে পয়েন্টগুলি ফেরত দেয় না। যেমন। p.pos যদি POINT(-179.88056 -16.68833)নিকটতম গ্রিড পয়েন্ট হতে পারে POINT(180 -16.25)তবে উপরের ক্যোয়ারীটি এটি ফেরত দেয় না। এটি ঠিক করার সর্বোত্তম উপায় কী?

আমি একক গ্রিড পয়েন্ট (-180 এবং +180) এর জন্য দুটি স্থানাঙ্ক রাখতে চাই না। আমি আমার নিজস্ব ফাংশনে যুক্ত করার চেষ্টা করেছি যা এই নির্দিষ্ট কেসের জন্য যাচাই করে তবে 5 মিনিটের মধ্যে কোয়েরিটি ফিরে আসে না, সম্ভবত কারণ এটি আর সূচকটি ব্যবহার করতে পারে না। আমি ST_DWithin এর ভৌগলিক সংস্করণটিও ব্যবহার করার চেষ্টা করেছি এবং সেই প্রশ্নটিও 5 মিনিটের পরে ফিরে আসেনি।


ভাল প্রশ্ন (এবং আপনার উত্তরে চতুর হ্যাক!)। যদিও একজনকে আশ্চর্য হতে হবে: যদি সফ্টওয়্যারটি দ্রাঘিমাংশের জন্য -180 = 180 সনাক্ত করতে অক্ষম হয়, তবে সম্ভবত এটি প্রজেক্টের স্থানাঙ্ক হিসাবে ভান করছে এবং নিকটস্থ পয়েন্টগুলি অনুসন্ধানের জন্য ইউক্লিডিয়ান অ্যালগরিদম ব্যবহার করছে, যা ত্রুটি তৈরি করতে চলেছে (সূক্ষ্ম কাছাকাছি সূক্ষ্ম) নিরক্ষীয় অঞ্চল, খুঁটির কাছাকাছি বিশাল এবং + -180 মেরিডিয়ান)। আমি জানি না যে এটি আপনার আবেদনে উল্লেখযোগ্য সমস্যার দিকে পরিচালিত করে কিনা, তবে অন্য অনেকের ক্ষেত্রে এটি ঘটবে, এবং যে চারপাশের কাজগুলি ত্রুটিগুলি নিরাময় করতে পারে না।
শুক্র

ভাল পয়েন্ট, তবে এক্ষেত্রে ক্লায়েন্ট অ্যাপ্লিকেশন অন্যান্য "নিকটতম" গণনা করবে না - এটি কেবল আমার ক্যোয়ারী থেকে ফিরে আসা গ্রিড পয়েন্টের সাথে যুক্ত কিছু ডেটা পাবে।
EM0

উত্তর:


6

ঠিক আছে, আমি অবশেষে এটি হ্যাক করার একটি উপায় বের করি যা কেবল ডেটলাইন ইস্যুতে কাজ করে না, তবে আরও দ্রুত।

CREATE OR REPLACE FUNCTION nearest_grid_point(point geography(Point))
RETURNS integer
AS $BODY$
    SELECT pointid
    FROM
    (
            -- The normal case
        SELECT pointid, location
        FROM grid
        WHERE ST_DWithin($1::geometry, location, 1)

        UNION ALL

            -- The dateline hack
        SELECT pointid, location
        FROM grid
        WHERE (ST_X($1::geometry) < -178.75 AND longitude = 180)
    ) sub
    ORDER BY ST_Distance($1, location::geography)
    LIMIT 1;
$BODY$ LANGUAGE SQL STABLE;

SELECT p.id, ST_AsText(p.pos), g.pointid, ST_AsText(g.location)
FROM point p
JOIN grid g ON nearest_grid_point(p.pos) = g.pointid

আমি খুব অবাক হয়ে দেখলাম যে প্রতিটি ফাংশনের জন্য ডাকা এই ফাংশনটি মূল উইন্ডো ফাংশনের চেয়ে দ্রুত, তবে এটি - 10 গুণ বেশি দ্রুত। পোস্টগ্র্যাস এসকিউএল পারফরম্যান্স সত্যিই একটি কালো শিল্প!

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.