যদি আপনি স্থানাঙ্ক টেবিলটিতে সহায়ক ক্ষেত্রগুলি যোগ করেন তবে আপনি কোয়েরির প্রতিক্রিয়া সময়কে উন্নত করতে পারেন।
এটার মত:
CREATE TABLE `Coordinates` (
`id` INT(10) UNSIGNED NOT NULL COMMENT 'id for the object',
`type` TINYINT(4) UNSIGNED NOT NULL DEFAULT '0' COMMENT 'type',
`sin_lat` FLOAT NOT NULL COMMENT 'sin(lat) in radians',
`cos_cos` FLOAT NOT NULL COMMENT 'cos(lat)*cos(lon) in radians',
`cos_sin` FLOAT NOT NULL COMMENT 'cos(lat)*sin(lon) in radians',
`lat` FLOAT NOT NULL COMMENT 'latitude in degrees',
`lon` FLOAT NOT NULL COMMENT 'longitude in degrees',
INDEX `lat_lon_idx` (`lat`, `lon`)
)
আপনি যদি টোকুডিবি ব্যবহার করে থাকেন তবে আপনি পূর্বাভাসগুলির মধ্যে দুটিতে ক্লাস্টারিং সূচক যুক্ত করলে আপনি আরও ভাল পারফরম্যান্স পাবেন, উদাহরণস্বরূপ:
alter table Coordinates add clustering index c_lat(lat);
alter table Coordinates add clustering index c_lon(lon);
আপনার ডিগ্রিগুলিতে বেসিক ল্যাট এবং লম্বা পাশাপাশি রেডিয়ানগুলিতে পাপ (ল্যাট), রেডিয়ানে কোস (ল্যাট) * কোস (লোন) এবং প্রতি পয়েন্টের জন্য রেডিয়ানে কোস (ল্যাট) * পাপ (লোন) প্রয়োজন হবে। তারপরে আপনি একটি মাইএসকিএল ফাংশন তৈরি করেন, এটি স্মার্ট:
CREATE FUNCTION `geodistance`(`sin_lat1` FLOAT,
`cos_cos1` FLOAT, `cos_sin1` FLOAT,
`sin_lat2` FLOAT,
`cos_cos2` FLOAT, `cos_sin2` FLOAT)
RETURNS float
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY INVOKER
BEGIN
RETURN acos(sin_lat1*sin_lat2 + cos_cos1*cos_cos2 + cos_sin1*cos_sin2);
END
এটি আপনাকে দূরত্ব দেয়।
ল্যাট / লম্বায় একটি সূচি যুক্ত করতে ভুলবেন না যাতে বাউন্ডিং বক্সিং অনুসন্ধানকে ধীর করার পরিবর্তে অনুসন্ধানে সহায়তা করতে পারে (উপরের ক্রিয়েট টেবিল কোয়েরিতে সূচিটি ইতিমধ্যে যুক্ত করা হয়েছে)।
INDEX `lat_lon_idx` (`lat`, `lon`)
শুধুমাত্র ল্যাট / দীর্ঘ স্থানাঙ্ক সহ একটি পুরানো সারণী দেওয়া, আপনি এটির আপডেট করার জন্য একটি স্ক্রিপ্ট সেট আপ করতে পারেন: (পিএইচপি মেকরোডব ব্যবহার করে)
$users = DB::query('SELECT id,lat,lon FROM Old_Coordinates');
foreach ($users as $user)
{
$lat_rad = deg2rad($user['lat']);
$lon_rad = deg2rad($user['lon']);
DB::replace('Coordinates', array(
'object_id' => $user['id'],
'object_type' => 0,
'sin_lat' => sin($lat_rad),
'cos_cos' => cos($lat_rad)*cos($lon_rad),
'cos_sin' => cos($lat_rad)*sin($lon_rad),
'lat' => $user['lat'],
'lon' => $user['lon']
));
}
তারপরে আপনি যখন সত্যই প্রয়োজন হবে তখন কেবল দূরত্ব গণনা করতে প্রকৃত ক্যোয়ারীটি অনুকূলিতকরণ করুন, উদাহরণস্বরূপ ভিতরে ভিতরে এবং বাইরে থেকে বৃত্তটি (ভাল, ডিম্বাকৃতি) আবদ্ধ করে। তার জন্য, আপনাকে নিজেরাই ক্যোয়ারির জন্য কয়েকটি মেট্রিকের প্রাক্ক্যালকুলেট করতে হবে:
// assuming the search center coordinates are $lat and $lon in degrees
// and radius in km is given in $distance
$lat_rad = deg2rad($lat);
$lon_rad = deg2rad($lon);
$R = 6371; // earth's radius, km
$distance_rad = $distance/$R;
$distance_rad_plus = $distance_rad * 1.06; // ovality error for outer bounding box
$dist_deg_lat = rad2deg($distance_rad_plus); //outer bounding box
$dist_deg_lon = rad2deg($distance_rad_plus/cos(deg2rad($lat)));
$dist_deg_lat_small = rad2deg($distance_rad/sqrt(2)); //inner bounding box
$dist_deg_lon_small = rad2deg($distance_rad/cos(deg2rad($lat))/sqrt(2));
এই প্রস্তুতিগুলি দেওয়া, ক্যোয়ারী এই জাতীয় কিছু হয়েছে (পিএইচপি):
$neighbors = DB::query("SELECT id, type, lat, lon,
geodistance(sin_lat,cos_cos,cos_sin,%d,%d,%d) as distance
FROM Coordinates WHERE
lat BETWEEN %d AND %d AND lon BETWEEN %d AND %d
HAVING (lat BETWEEN %d AND %d AND lon BETWEEN %d AND %d) OR distance <= %d",
// center radian values: sin_lat, cos_cos, cos_sin
sin($lat_rad),cos($lat_rad)*cos($lon_rad),cos($lat_rad)*sin($lon_rad),
// min_lat, max_lat, min_lon, max_lon for the outside box
$lat-$dist_deg_lat,$lat+$dist_deg_lat,
$lon-$dist_deg_lon,$lon+$dist_deg_lon,
// min_lat, max_lat, min_lon, max_lon for the inside box
$lat-$dist_deg_lat_small,$lat+$dist_deg_lat_small,
$lon-$dist_deg_lon_small,$lon+$dist_deg_lon_small,
// distance in radians
$distance_rad);
উপরের ক্যোয়ারির ব্যাখ্যা দিয়ে বলতে পারেন যে এটির সূচক ব্যবহার করা হচ্ছে না যদি না এর মধ্যে ট্রিগার করার যথেষ্ট ফলাফল থাকে। স্থানাঙ্ক টেবিলের পর্যাপ্ত ডেটা থাকলে সূচকটি ব্যবহার করা হবে। আপনি টেবিলের আকারের সাথে কোনও সূচক না রেখে সূচকটি ব্যবহার করতে SELECT এ ফোর্স ইন্ডেক্স (ল্যাট_লোন_আইডিএক্স) যুক্ত করতে পারেন, যাতে আপনি এটি সঠিকভাবে কাজ করছে তা এক্সপ্লেইন দিয়ে যাচাই করতে পারেন।
উপরের কোডের নমুনাগুলির সাথে আপনার ন্যূনতম ত্রুটি সহ দূরত্বে অবজেক্ট অনুসন্ধানের একটি কার্যকরী এবং স্কেলযোগ্য বাস্তবায়ন হওয়া উচিত।