فصل 4. إدارة البيانات
4.1. نموذج البيانات المكانية
4.1.1. الشكل الهندسي وفق OGC
طوّر اتحاد Open Geospatial Consortium (OGC) معيار Simple Features Access (SFA) لتوفير نموذج للبيانات الجغرافية المكانية. ويُعرّف هذا المعيار النوع المكاني الأساسي Geometry، إلى جانب العمليات التي تعالج قيم الأشكال الهندسية وتحوّلها لإنجاز مهام التحليل المكاني. ويطبّق PostGIS نموذج OGC Geometry في صورة نوعَي البيانات geometry وgeography في PostgreSQL.
النوع Geometry نوع مجرّد. وتنتمي قيم الأشكال الهندسية إلى أحد أنواعه الفرعية الملموسة التي تمثّل أصنافًا وأبعادًا مختلفة من الأشكال الهندسية. ومنها الأنواع الذرّية Point وLineString وLinearRing وPolygon، وأنواع المجموعات MultiPoint وMultiLineString وMultiPolygon وGeometryCollection. ويضيف معيار Simple Features Access - Part 1: Common architecture v1.2.1 أنواعًا فرعية للبنى PolyhedralSurface وTriangle وTIN.
يمثّل النوع Geometry الأشكال في المستوى الديكارتي ثنائي الأبعاد. ويمكن للأنواع PolyhedralSurface وTriangle وTIN أن تمثّل أيضًا أشكالًا في الفضاء ثلاثي الأبعاد. ويُحدَّد حجم الأشكال وموقعها بواسطة إحداثياتها. ولكل إحداثية قيمتا إحداثي X وY تحددان موقعها في المستوى. وتُبنى الأشكال من نقاط أو قطع مستقيمة، إذ تُحدَّد النقطة بإحداثية واحدة، والقطعة المستقيمة بإحداثيتين.
قد تحتوي الإحداثيات على قيمتَي الإحداثي الاختياريتين Z وM. يُستخدم الإحداثي Z غالبًا لتمثيل الارتفاع. ويحتوي الإحداثي M على قيمة قياس، قد تمثّل الزمن أو المسافة. وإذا وُجدت قيم Z أو M في قيمة شكل هندسي، فيجب أن تكون معرّفة لكل نقطة في الشكل. وإذا كان للشكل الهندسي إحداثي Z أو M فإن بُعد الإحداثيات يكون 3D؛ وإذا كان له Z وM معًا فبُعد الإحداثيات 4D.
ترتبط قيم الأشكال الهندسية بـنظام مرجعي مكاني يدل على نظام الإحداثيات الذي تقع فيه. ويُعرَّف النظام المرجعي المكاني برقم SRID الخاص بالشكل الهندسي. ويحدد النظام المرجعي المكاني وحدات المحورين X وY. ففي الأنظمة المرجعية المستوية تمثّل الإحداثيات X وY عادةً الإزاحة شرقًا والإزاحة شمالًا، بينما تمثّل في الأنظمة الجيوديسية خط الطول ودائرة العرض. ويمثّل SRID 0 مستوًى ديكارتيًا لا نهائيًا بلا وحدات لمحاوره. راجع قسم 4.5, “الأنظمة المرجعية المكانية”.
بُعد الشكل الهندسي خاصية من خصائص أنواع الأشكال الهندسية. فبُعد أنواع النقاط 0، وبُعد الأنواع الخطية 1، وبُعد الأنواع المضلعية 2. وبُعد المجموعات هو أكبر أبعاد عناصرها.
قد تكون قيمة الشكل الهندسي فارغة. والقيم الفارغة لا تحتوي على رؤوس (في أنواع الأشكال الذرّية) أو على عناصر (في المجموعات).
من الخصائص المهمة لقيم الأشكال الهندسية امتدادها المكاني أو المستطيل المحيط بها، الذي يسميه نموذج OGC الغلاف. وهو الصندوق ثنائي أو ثلاثي الأبعاد الذي يحيط بإحداثيات الشكل الهندسي. ويُعد وسيلة فعّالة لتمثيل امتداد الشكل في فضاء الإحداثيات وللتحقق مما إذا كان شكلان هندسيان يتفاعلان.
يتيح نموذج الأشكال الهندسية تقييم العلاقات المكانية الطوبولوجية كما هو موضّح في قسم 5.1.1, “نموذج التقاطعات التسعة الموسّع بالأبعاد”. ولدعم ذلك تُعرَّف مفاهيم الداخل والحد والخارج لكل نوع من أنواع الأشكال الهندسية. والأشكال الهندسية مغلقة طوبولوجيًا، لذا فهي تحتوي دائمًا على حدها. والحد شكل هندسي بُعده أقل بواحد من بُعد الشكل نفسه.
يُعرّف نموذج OGC للأشكال الهندسية قواعد صلاحية لكل نوع من أنواعها. وتضمن هذه القواعد أن تمثّل قيم الأشكال الهندسية حالات واقعية (فمثلًا يمكن تحديد مضلع فيه ثقب يقع خارج الغلاف الخارجي، لكن هذا لا معنى له هندسيًا ولذا فهو غير صالح). ويسمح PostGIS أيضًا بتخزين قيم الأشكال الهندسية غير الصالحة ومعالجتها، مما يتيح اكتشافها وإصلاحها عند الحاجة. راجع قسم 4.4, “التحقق من صلاحية الأشكال الهندسية”
4.1.1.1. Point
النقطة (Point) شكل هندسي صفري البعد يمثّل موقعًا واحدًا في فضاء الإحداثيات.
POINT (1 2) POINT Z (1 2 3) POINT ZM (1 2 3 4)
4.1.1.2. LineString
الخط (LineString) خط أحادي البعد يتكوّن من تتابع متصل من القطع المستقيمة. وتُعرَّف كل قطعة بنقطتين، وتكون نقطة نهاية كل قطعة هي نقطة بداية القطعة التالية. والخط الصالح وفق OGC يحتوي إما على صفر من النقاط أو على نقطتين أو أكثر، لكن PostGIS يسمح أيضًا بخطوط ذات نقطة واحدة. وقد تعبر الخطوط نفسها (تتقاطع ذاتيًا). ويكون الخط مغلقًا إذا تطابقت نقطتا بدايته ونهايته. ويكون الخط بسيطًا إذا لم يتقاطع ذاتيًا.
LINESTRING (1 2, 3 4, 5 6)
4.1.1.3. LinearRing
الحلقة الخطية (LinearRing) خط مغلق وبسيط في آن واحد. يجب أن تتساوى النقطتان الأولى والأخيرة، وألا يتقاطع الخط ذاتيًا.
LINEARRING (0 0 0, 4 0 0, 4 4 0, 0 4 0, 0 0 0)
4.1.1.4. Polygon
المضلع (Polygon) منطقة مستوية ثنائية الأبعاد، يحدّها حد خارجي (الغلاف) وصفر أو أكثر من الحدود الداخلية (الثقوب). وكل حد هو LinearRing.
POLYGON ((0 0 0,4 0 0,4 4 0,0 4 0,0 0 0),(1 1 0,2 1 0,2 2 0,1 2 0,1 1 0))
4.1.1.5. MultiPoint
النقطة المتعددة (MultiPoint) مجموعة من النقاط.
MULTIPOINT ( (0 0), (1 2) )
4.1.1.6. MultiLineString
الخط المتعدد (MultiLineString) مجموعة من الخطوط. ويكون الخط المتعدد مغلقًا إذا كان كل عنصر من عناصره مغلقًا.
MULTILINESTRING ( (0 0,1 1,1 2), (2 3,3 2,5 4) )
4.1.1.7. MultiPolygon
المضلع المتعدد (MultiPolygon) مجموعة من المضلعات غير المتداخلة وغير المتجاورة. ولا يجوز أن تتلامس مضلعات المجموعة إلا في عدد محدود من النقاط.
MULTIPOLYGON (((1 5, 5 5, 5 1, 1 1, 1 5)), ((6 5, 9 1, 6 1, 6 5)))
4.1.1.8. GeometryCollection
مجموعة الأشكال (GeometryCollection) مجموعة غير متجانسة (مختلطة) من الأشكال الهندسية.
GEOMETRYCOLLECTION ( POINT(2 3), LINESTRING(2 3, 3 4))
4.1.1.9. PolyhedralSurface
السطح متعدد الوجوه (PolyhedralSurface) مجموعة متصلة من الرقع أو الأوجه التي تشترك في بعض الحواف. وكل رقعة مضلع مستوٍ. وإذا كانت لإحداثيات المضلع قيم Z فإن السطح يكون ثلاثي الأبعاد.
POLYHEDRALSURFACE Z ( ((0 0 0, 0 0 1, 0 1 1, 0 1 0, 0 0 0)), ((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)), ((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)), ((1 1 0, 1 1 1, 1 0 1, 1 0 0, 1 1 0)), ((0 1 0, 0 1 1, 1 1 1, 1 1 0, 0 1 0)), ((0 0 1, 1 0 1, 1 1 1, 0 1 1, 0 0 1)) )
4.1.1.10. Triangle
المثلث (Triangle) مضلع يُعرَّف بثلاثة رؤوس متمايزة غير واقعة على استقامة واحدة. ولأن المثلث مضلع فهو يُحدَّد بأربع إحداثيات، تكون الأولى والرابعة منها متساويتين.
TRIANGLE ((0 0, 0 9, 9 0, 0 0))
4.1.1.11. TIN
شبكة TIN مجموعة من المثلثات (Triangle) غير المتداخلة تمثّل شبكة مثلثات غير منتظمة.
TIN Z ( ((0 0 0, 0 0 1, 0 1 0, 0 0 0)), ((0 0 0, 0 1 0, 1 1 0, 0 0 0)) )
4.1.2. SQL/MM الجزء 3 - المنحنيات
يوسّع معيار ISO/IEC 13249-3 SQL Multimedia - Spatial (SQL/MM) معيار OGC SFA بتعريف أنواع فرعية من Geometry تحتوي على منحنيات ذات أقواس دائرية. وتدعم أنواع SQL/MM الإحداثيات 3DM و3DZ و4D.
|
|
|
تُجرى جميع مقارنات الأعداد العشرية في تطبيق SQL-MM ضمن تفاوت محدد، قيمته حاليًا 1E-8. |
4.1.2.1. CircularString
القوس الدائري (CircularString) هو نوع المنحنى الأساسي، ويشبه الخط (LineString) في العالم الخطي. ويُحدَّد مقطع القوس الواحد بثلاث نقاط: نقطتَي البداية والنهاية (الأولى والثالثة) ونقطة أخرى على القوس. ولتحديد دائرة مغلقة تكون نقطتا البداية والنهاية متطابقتين وتكون النقطة الوسطى هي النقطة المقابلة على قطر الدائرة (وهو مركز القوس). وفي تتابع الأقواس تكون نقطة نهاية القوس السابق هي نقطة بداية القوس التالي، تمامًا كقطع الخط. وهذا يعني أن القوس الدائري يجب أن يحتوي على عدد فردي من النقاط أكبر من 1.
CIRCULARSTRING(0 0, 1 1, 1 0) CIRCULARSTRING(0 0, 4 0, 4 4, 0 4, 0 0)
4.1.2.2. CompoundCurve
المنحنى المركّب (CompoundCurve) منحنى واحد متصل قد يحتوي على مقاطع أقواس دائرية ومقاطع خطية معًا. وهذا يعني أنه، إضافةً إلى سلامة بناء المكوّنات، يجب أن تتطابق نقطة نهاية كل مكوّن (باستثناء الأخير) مع نقطة بداية المكوّن التالي.
COMPOUNDCURVE( CIRCULARSTRING(0 0, 1 1, 1 0),(1 0, 0 1))
4.1.2.3. CurvePolygon
المضلع المنحني (CurvePolygon) يشبه المضلع، إذ له حلقة خارجية وصفر أو أكثر من الحلقات الداخلية. والفرق أن الحلقة يمكن أن تكون CircularString أو CompoundCurve إضافةً إلى LineString.
بدءًا من PostGIS 1.4 يدعم PostGIS المنحنيات المركّبة في المضلع المنحني.
CURVEPOLYGON( CIRCULARSTRING(0 0, 4 0, 4 4, 0 4, 0 0), (1 1, 3 3, 3 1, 1 1) )
مثال: مضلع منحني (CurvePolygon) غلافه معرّف بمنحنى مركّب (CompoundCurve) يحتوي على قوس دائري (CircularString) وخط (LineString)، وثقبه معرّف بقوس دائري (CircularString)
CURVEPOLYGON(
COMPOUNDCURVE( CIRCULARSTRING(0 0,2 0, 2 1, 2 3, 4 3),
(4 3, 4 5, 1 4, 0 0)),
CIRCULARSTRING(1.7 1, 1.4 0.4, 1.6 0.4, 1.6 0.5, 1.7 1) )
4.1.2.4. MultiCurve
المنحنى المتعدد (MultiCurve) مجموعة من المنحنيات يمكن أن تشمل LineString أو CircularString أو CompoundCurve.
MULTICURVE( (0 0, 5 5), CIRCULARSTRING(4 0, 4 4, 8 4))
4.1.2.5. MultiSurface
السطح المتعدد (MultiSurface) مجموعة من الأسطح، يمكن أن تكون مضلعات (خطية) أو مضلعات منحنية (CurvePolygon).
MULTISURFACE(
CURVEPOLYGON(
CIRCULARSTRING( 0 0, 4 0, 4 4, 0 4, 0 0),
(1 1, 3 3, 3 1, 1 1)),
((10 10, 14 12, 11 10, 10 10), (11 11, 11.5 11, 11 11.5, 11 11)))
4.1.3. WKT وWKB
تُعرّف مواصفة OGC SFA صيغتين لتمثيل قيم الأشكال الهندسية للاستخدام الخارجي: Well-Known Text (WKT) وWell-Known Binary (WKB). وتتضمن كلتا الصيغتين WKT وWKB معلومات عن نوع الكائن والإحداثيات التي تعرّفه.
توفّر صيغة Well-Known Text (WKT) تمثيلًا نصيًا قياسيًا للبيانات المكانية. ومن أمثلة تمثيلات WKT للكائنات المكانية:
-
POINT(0 0)
-
POINT Z (0 0 0)
-
POINT ZM (0 0 0 0)
-
POINT EMPTY
-
LINESTRING(0 0,1 1,1 2)
-
LINESTRING EMPTY
-
POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1))
-
MULTIPOINT((0 0),(1 2))
-
MULTIPOINT Z ((0 0 0),(1 2 3))
-
MULTIPOINT EMPTY
-
MULTILINESTRING((0 0,1 1,1 2),(2 3,3 2,5 4))
-
MULTIPOLYGON(((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1)), ((-1 -1,-1 -2,-2 -2,-2 -1,-1 -1)))
-
GEOMETRYCOLLECTION(POINT(2 3),LINESTRING(2 3,3 4))
-
GEOMETRYCOLLECTION EMPTY
يتوفر إدخال WKT وإخراجه عبر الدالتين ST_AsText وST_GeomFromText:
text WKT = ST_AsText(geometry); geometry = ST_GeomFromText(text WKT, SRID);
على سبيل المثال، هذه تعليمة لإنشاء كائن مكاني من WKT وSRID وإدراجه:
INSERT INTO geotable ( geom, name )
VALUES ( ST_GeomFromText('POINT(-126.4 45.32)', 312), 'A Place');
توفّر صيغة Well-Known Binary (WKB) تمثيلًا محمولًا وكامل الدقة للبيانات المكانية في صورة بيانات ثنائية (مصفوفات من البايتات). ومن أمثلة تمثيلات WKB للكائنات المكانية:
-
WKT: POINT(1 1)
WKB: 0101000000000000000000F03F000000000000F03
-
WKT: LINESTRING (2 2, 9 9)
WKB: 0102000000020000000000000000000040000000000000004000000000000022400000000000002240
يتوفر إدخال WKB وإخراجه عبر الدالتين ST_AsBinary وST_GeomFromWKB:
bytea WKB = ST_AsBinary(geometry); geometry = ST_GeomFromWKB(bytea WKB, SRID);
على سبيل المثال، هذه تعليمة لإنشاء كائن مكاني من WKB وإدراجه:
INSERT INTO geotable ( geom, name )
VALUES ( ST_GeomFromWKB('\x0101000000000000000000f03f000000000000f03f', 312), 'A Place');
4.2. نوع البيانات Geometry
يطبّق PostGIS نموذج OGC Simple Features بتعريف نوع بيانات في PostgreSQL يُسمى geometry. ويمثّل هذا النوع جميع الأنواع الفرعية للأشكال الهندسية باستخدام رمز نوع داخلي (راجع GeometryType وST_GeometryType). ويتيح ذلك نمذجة المعالم المكانية في صورة صفوف في جداول معرّفة بعمود من النوع geometry.
نوع البيانات geometry نوع معتم، أي إن كل وصول إليه يتم عبر استدعاء دوال على قيم الأشكال الهندسية. وتتيح الدوال إنشاء كائنات هندسية، والوصول إلى جميع الحقول الداخلية أو تحديثها، وحساب قيم هندسية جديدة. ويدعم PostGIS جميع الدوال المحددة في مواصفة OGC Simple feature access - Part 2: SQL option (SFS)، إضافةً إلى دوال أخرى كثيرة. راجع فصل 7, مرجع PostGIS للاطلاع على القائمة الكاملة للدوال.
|
|
|
يتّبع PostGIS معيار SFA في إضافة البادئة "ST_" إلى أسماء الدوال المكانية. وكان المقصود منها أصلًا "Spatial and Temporal" (مكاني وزمني)، لكن الجزء الزمني من المعيار لم يُطوَّر قط. وبدلًا من ذلك يمكن تفسيرها بأنها "Spatial Type" (نوع مكاني). |
ينص معيار SFA على أن الكائنات المكانية تتضمن معرّف النظام المرجعي المكاني (SRID). ويلزم SRID عند إنشاء كائنات مكانية لإدراجها في قاعدة البيانات (وقد تكون قيمته الافتراضية 0). راجع ST_SRID وقسم 4.5, “الأنظمة المرجعية المكانية”
لجعل الاستعلام عن الأشكال الهندسية فعّالًا، يُعرّف PostGIS أنواعًا مختلفة من الفهارس المكانية، ومعاملات مكانية لاستخدامها. راجع قسم 4.9, “الفهارس المكانية” وقسم 5.2, “استخدام الفهارس المكانية” للتفاصيل.
4.2.1. صيغتا EWKB وEWKT في PostGIS
لم تكن مواصفات OGC SFA تدعم في البداية إلا الأشكال الهندسية ثنائية الأبعاد، ولا يُضمَّن SRID الشكل الهندسي في تمثيلات الإدخال/الإخراج. وتضيف مواصفة OGC SFA 1.2.1 (المتوافقة مع معيار ISO 19125) دعم الإحداثيات ثلاثية الأبعاد (ZYZ) والمقيسة (XYM وXYZM)، لكنها لا تزال لا تتضمن قيمة SRID.
بسبب هذه القيود عرّف PostGIS الصيغتين الموسّعتين EWKB وEWKT. وهما توفّران دعم الإحداثيات ثلاثية الأبعاد (XYZ وXYM) ورباعية الأبعاد (XYZM) وتتضمنان معلومات SRID. ويتيح تضمين جميع معلومات الشكل الهندسي لـ PostGIS استخدام EWKB صيغةً معتمدة للتسجيل (مثلًا في ملفات DUMP).
تُستخدم EWKB وEWKT في "الصيغ القانونية" لكائنات بيانات PostGIS. ففي الإدخال، الصيغة القانونية للبيانات الثنائية هي EWKB، أما البيانات النصية فتُقبل فيها EWKB أو EWKT. ويتيح ذلك إنشاء قيم هندسية بتحويل قيمة نصية بصيغة HEXEWKB أو EWKT إلى قيمة geometry باستخدام ::geometry. وفي الإخراج، الصيغة القانونية للبيانات الثنائية هي EWKB، وللنصية HEXEWKB (EWKB مرمّزة ست عشريًا).
على سبيل المثال، تنشئ هذه التعليمة شكلًا هندسيًا بالتحويل من قيمة نصية بصيغة EWKT، وتُخرجه بالصيغة القانونية HEXEWKB:
SELECT 'SRID=4;POINT(0 0)'::geometry; geometry ---------------------------------------------------- 01010000200400000000000000000000000000000000000000
يختلف إخراج EWKT في PostGIS عن OGC WKT في بضعة أمور:
-
في الأشكال الهندسية 3DZ يُحذف المؤهِّل Z:
OGC: POINT Z (1 2 3)
EWKT: POINT (1 2 3)
-
في الأشكال الهندسية 3DM يُضمَّن المؤهِّل M:
OGC: POINT M (1 2 3)
EWKT: POINTM (1 2 3)
-
في الأشكال الهندسية 4D يُحذف المؤهِّل ZM:
OGC: POINT ZM (1 2 3 4)
EWKT: POINT (1 2 3 4)
تتجنب EWKT الإفراط في تحديد الأبعاد وحالات عدم الاتساق التي قد تقع مع صيغة OGC/ISO، مثل:
-
POINT ZM (1 1)
-
POINT ZM (1 1 1)
-
POINT (1 1 1 1)
|
|
|
الصيغ الموسّعة في PostGIS حاليًا مجموعة شاملة لصيغ OGC، بحيث تكون كل قيمة WKB/WKT صالحة وفق OGC صالحةً أيضًا بوصفها EWKB/EWKT. غير أن ذلك قد يتغيّر مستقبلًا إذا وسّع OGC صيغةً ما بطريقة تتعارض مع تعريف PostGIS. لذا يجب ألا تعتمد على هذا التوافق! |
من أمثلة التمثيل النصي EWKT للكائنات المكانية:
-
POINT(0 0 0) -- XYZ
-
SRID=32632;POINT(0 0) -- XY مع SRID
-
POINTM(0 0 0) -- XYM
-
POINT(0 0 0 0) -- XYZM
-
SRID=4326;MULTIPOINTM(0 0 0,1 2 1) -- XYM مع SRID
-
MULTILINESTRING((0 0 0,1 1 0,1 2 1),(2 3 1,3 2 1,5 4 1))
-
POLYGON((0 0 0,4 0 0,4 4 0,0 4 0,0 0 0),(1 1 0,2 1 0,2 2 0,1 2 0,1 1 0))
-
MULTIPOLYGON(((0 0 0,4 0 0,4 4 0,0 4 0,0 0 0),(1 1 0,2 1 0,2 2 0,1 2 0,1 1 0)),((-1 -1 0,-1 -2 0,-2 -2 0,-2 -1 0,-1 -1 0)))
-
GEOMETRYCOLLECTIONM( POINTM(2 3 9), LINESTRINGM(2 3 4, 3 4 5) )
-
MULTICURVE( (0 0, 5 5), CIRCULARSTRING(4 0, 4 4, 8 4) )
-
POLYHEDRALSURFACE( ((0 0 0, 0 0 1, 0 1 1, 0 1 0, 0 0 0)), ((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)), ((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)), ((1 1 0, 1 1 1, 1 0 1, 1 0 0, 1 1 0)), ((0 1 0, 0 1 1, 1 1 1, 1 1 0, 0 1 0)), ((0 0 1, 1 0 1, 1 1 1, 0 1 1, 0 0 1)) )
-
TRIANGLE ((0 0, 0 10, 10 0, 0 0))
-
TIN( ((0 0 0, 0 0 1, 0 1 0, 0 0 0)), ((0 0 0, 0 1 0, 1 1 0, 0 0 0)) )
يتوفر الإدخال والإخراج بهذه الصيغ عبر الدوال التالية:
bytea EWKB = ST_AsEWKB(geometry); text EWKT = ST_AsEWKT(geometry); geometry = ST_GeomFromEWKB(bytea EWKB); geometry = ST_GeomFromEWKT(text EWKT);
على سبيل المثال، هذه تعليمة لإنشاء كائن مكاني في PostGIS باستخدام EWKT وإدراجه:
INSERT INTO geotable ( geom, name )
VALUES ( ST_GeomFromEWKT('SRID=312;POINTM(-126.4 45.32 15)'), 'A Place' )
4.3. نوع البيانات Geography
يوفّر نوع البيانات geography في PostGIS دعمًا أصيلًا للمعالم المكانية الممثَّلة بإحداثيات "جغرافية" (تُسمى أحيانًا إحداثيات "جيوديسية"، أو "lat/lon"، أو "lon/lat"). والإحداثيات الجغرافية إحداثيات كروية معبَّر عنها بوحدات زاوية (درجات).
أساس نوع البيانات geometry في PostGIS هو المستوى. وأقصر مسار بين نقطتين على المستوى هو الخط المستقيم. وهذا يعني أن الدوال على الأشكال الهندسية (المساحات، والمسافات، والأطوال، والتقاطعات، وغيرها) تُحسب باستخدام متجهات الخطوط المستقيمة والرياضيات الديكارتية. وهذا يجعلها أبسط تطبيقًا وأسرع تنفيذًا، لكنه يجعلها أيضًا غير دقيقة للبيانات الواقعة على سطح الأرض الإهليلجي.
يقوم نوع البيانات geography في PostGIS على نموذج كروي. وأقصر مسار بين نقطتين على الكرة هو قوس من دائرة عظمى. وتُحسب الدوال على البيانات الجغرافية (المساحات، والمسافات، والأطوال، والتقاطعات، وغيرها) باستخدام أقواس على الكرة. وبأخذ الشكل الإهليلجي للأرض في الحسبان، تقدّم الدوال نتائج أدق.
لأن الرياضيات الأساسية أكثر تعقيدًا، فإن الدوال المعرّفة للنوع geography أقل من تلك المعرّفة للنوع geometry. ومع مرور الوقت وإضافة خوارزميات جديدة ستتوسع قدرات النوع geography. وكحل بديل يمكن التحويل ذهابًا وإيابًا بين النوعين geometry وgeography.
كما في نوع البيانات geometry، ترتبط بيانات geography بنظام مرجعي مكاني عبر معرّف النظام المرجعي المكاني (SRID). ويمكن استخدام أي نظام مرجعي مكاني جيوديسي (قائم على خط الطول/دائرة العرض) معرّف في الجدول spatial_ref_sys. (قبل PostGIS 2.2 كان النوع geography لا يدعم إلا النظام الجيوديسي WGS 84 (SRID:4326)). ويمكنك إضافة نظامك المرجعي المكاني الجيوديسي المخصص كما هو موضّح في قسم 4.5.2, “الأنظمة المرجعية المكانية المعرّفة من المستخدم”.
في جميع الأنظمة المرجعية المكانية تكون الوحدات التي تُعيدها دوال القياس (مثل ST_Distance وST_Length وST_Perimeter وST_Area) ووحدات وسيط المسافة في ST_DWithin بالأمتار.
4.3.1. إنشاء جداول Geography
يمكنك إنشاء جدول لتخزين بيانات geography باستخدام تعليمة SQL CREATE TABLE مع عمود من النوع geography. ينشئ المثال التالي جدولًا فيه عمود geography يخزّن خطوطًا ثنائية الأبعاد في نظام الإحداثيات الجيوديسي WGS84 (SRID 4326):
CREATE TABLE global_points (
id SERIAL PRIMARY KEY,
name VARCHAR(64),
location geography(POINT,4326)
);
يدعم النوع geography مُعدِّلَي نوع اختياريين:
-
مُعدِّل النوع المكاني يقيّد صنف الأشكال وأبعادها المسموح بها في العمود. والقيم المسموح بها للنوع المكاني هي: POINT وLINESTRING وPOLYGON وMULTIPOINT وMULTILINESTRING وMULTIPOLYGON وGEOMETRYCOLLECTION. ولا يدعم النوع geography المنحنيات ولا TINS ولا POLYHEDRALSURFACE. ويدعم المُعدِّل تقييد أبعاد الإحداثيات بإضافة اللواحق: Z وM وZM. فمثلًا المُعدِّل 'LINESTRINGM' لا يسمح إلا بخطوط ثلاثية الأبعاد، ويعامل البعد الثالث بوصفه قياسًا. وبالمثل، يتطلب 'POINTZM' بيانات رباعية الأبعاد (XYZM).
-
مُعدِّل SRID يقيّد SRID النظام المرجعي المكاني برقم معيّن. وإذا حُذف، تكون القيمة الافتراضية لـ SRID هي 4326 (WGS84 الجيوديسي)، وتُجرى جميع الحسابات باستخدام WGS84.
أمثلة على إنشاء جداول بأعمدة geography:
-
إنشاء جدول بنقاط POINT ثنائية الأبعاد من النوع geography مع SRID الافتراضي 4326 (WGS84 خط الطول/دائرة العرض):
CREATE TABLE ptgeogwgs(gid serial PRIMARY KEY, geog geography(POINT) );
-
إنشاء جدول بنقاط POINT ثنائية الأبعاد من النوع geography في NAD83 بخط الطول/دائرة العرض:
CREATE TABLE ptgeognad83(gid serial PRIMARY KEY, geog geography(POINT,4269) );
-
إنشاء جدول بنقاط POINT ثلاثية الأبعاد (XYZ) مع SRID صريح قيمته 4326:
CREATE TABLE ptzgeogwgs84(gid serial PRIMARY KEY, geog geography(POINTZ,4326) );
-
إنشاء جدول بخطوط LINESTRING ثنائية الأبعاد من النوع geography مع SRID الافتراضي 4326:
CREATE TABLE lgeog(gid serial PRIMARY KEY, geog geography(LINESTRING) );
-
إنشاء جدول بمضلعات POLYGON ثنائية الأبعاد من النوع geography مع SRID 4267 (NAD 1927 خط الطول/دائرة العرض):
CREATE TABLE lgeognad27(gid serial PRIMARY KEY, geog geography(POLYGON,4267) );
تُسجَّل حقول geography في عرض النظام geography_columns. ويمكنك الاستعلام من العرض geography_columns لترى أن الجدول مُدرج فيه:
SELECT * FROM geography_columns;
إنشاء فهرس مكاني يتم بالطريقة نفسها المتبعة مع أعمدة geometry. سيلاحظ PostGIS أن نوع العمود هو GEOGRAPHY وسينشئ فهرسًا مناسبًا قائمًا على الكرة بدلًا من الفهرس المستوي المعتاد المستخدم مع GEOMETRY.
-- Index the test table with a spherical index CREATE INDEX global_points_gix ON global_points USING GIST ( location );
4.3.2. استخدام جداول Geography
يمكنك إدراج البيانات في جداول geography بالطريقة نفسها المتبعة مع geometry. وستُحوَّل بيانات geometry تلقائيًا إلى النوع geography إذا كان SRID الخاص بها 4326. ويمكن أيضًا استخدام الصيغتين EWKT وEWKB لتحديد قيم geography.
-- Add some data into the test table
INSERT INTO global_points (name, location) VALUES ('Town', 'SRID=4326;POINT(-110 30)');
INSERT INTO global_points (name, location) VALUES ('Forest', 'SRID=4326;POINT(-109 29)');
INSERT INTO global_points (name, location) VALUES ('London', 'SRID=4326;POINT(0 49)');
يمكن تحديد أي نظام مرجعي مكاني جيوديسي (خط الطول/دائرة العرض) مُدرج في الجدول spatial_ref_sys بوصفه SRID لبيانات geography. أما أنظمة الإحداثيات غير الجيوديسية فتُطلق خطأً عند استخدامها.
-- NAD 83 lon/lat
SELECT 'SRID=4269;POINT(-123 34)'::geography;
geography
----------------------------------------------------
0101000020AD1000000000000000C05EC00000000000004140
-- NAD27 lon/lat
SELECT 'SRID=4267;POINT(-123 34)'::geography;
geography
----------------------------------------------------
0101000020AB1000000000000000C05EC00000000000004140
-- NAD83 UTM zone meters - gives an error since it is a meter-based planar projection SELECT 'SRID=26910;POINT(-123 34)'::geography; ERROR: Only lon/lat coordinate systems are supported in geography.
تستخدم دوال الاستعلام والقياس وحدة المتر. لذا يجب التعبير عن معاملات المسافة بالأمتار، وتوقّع القيم المُعادة بالأمتار (أو بالأمتار المربعة للمساحات).
-- A distance query using a 1000km tolerance SELECT name FROM global_points WHERE ST_DWithin(location, 'SRID=4326;POINT(-110 29)'::geography, 1000000);
يمكنك رؤية قوة geography عمليًا بحساب مدى اقتراب طائرة تحلّق في مسار دائرة عظمى من سياتل إلى لندن (LINESTRING(-122.33 47.606, 0.0 51.5)) من ريكيافيك (POINT(-21.96 64.15)) (ارسم المسار على الخريطة).
يحسب النوع geography المسافة الحقيقية الأقصر البالغة 122.235 كم على الكرة بين ريكيافيك ومسار رحلة الدائرة العظمى بين سياتل ولندن.
-- Distance calculation using GEOGRAPHY
SELECT ST_Distance('LINESTRING(-122.33 47.606, 0.0 51.5)'::geography, 'POINT(-21.96 64.15)'::geography);
st_distance
-----------------
122235.23815667
أما النوع geometry فيحسب مسافة ديكارتية لا معنى لها بين ريكيافيك ومسار الخط المستقيم من سياتل إلى لندن مرسومًا على خريطة مسطحة للعالم. والوحدات الاسمية للنتيجة هي "الدرجات"، لكن النتيجة لا تقابل أي فرق زاوي حقيقي بين النقاط، لذا فحتى تسميتها "درجات" غير دقيقة.
-- Distance calculation using GEOMETRY
SELECT ST_Distance('LINESTRING(-122.33 47.606, 0.0 51.5)'::geometry, 'POINT(-21.96 64.15)'::geometry);
st_distance
--------------------
13.342271221453624
4.3.3. متى تستخدم نوع البيانات Geography
يتيح لك نوع البيانات geography تخزين البيانات بإحداثيات خط الطول/دائرة العرض، لكن بثمن: فالدوال المعرّفة على GEOGRAPHY أقل من تلك المعرّفة على GEOMETRY؛ والدوال المعرّفة منها تستغرق وقت معالجة أطول عند التنفيذ.
ينبغي أن يُحدَّد نوع البيانات الذي تختاره بناءً على منطقة العمل المتوقعة للتطبيق الذي تبنيه. هل ستمتد بياناتك على الكرة الأرضية كلها أو على منطقة قارية واسعة، أم أنها محلية على مستوى ولاية أو مقاطعة أو بلدية؟
-
إذا كانت بياناتك محصورة في منطقة صغيرة، فقد تجد أن اختيار إسقاط مناسب واستخدام GEOMETRY هو الحل الأفضل من حيث الأداء والوظائف المتاحة.
-
إذا كانت بياناتك عالمية أو تغطي منطقة قارية، فقد تجد أن GEOGRAPHY يتيح لك بناء نظام دون الحاجة إلى القلق بشأن تفاصيل الإسقاط. فتخزّن بياناتك بخط الطول/دائرة العرض، وتستخدم الدوال المعرّفة على GEOGRAPHY.
-
إذا كنت لا تفهم الإسقاطات، ولا تريد أن تتعلمها، وكنت مستعدًا لقبول القيود على الوظائف المتاحة في GEOGRAPHY، فقد يكون استخدام GEOGRAPHY أسهل لك من GEOMETRY. ما عليك إلا تحميل بياناتك بخط الطول/دائرة العرض والانطلاق من هناك.
راجع قسم 13.11, “مصفوفة دعم دوال PostGIS” للمقارنة بين ما هو مدعوم في Geography مقابل Geometry. وللاطلاع على قائمة موجزة بدوال Geography ووصفها، راجع قسم 13.4, “دوال PostGIS الداعمة لنوع geography”
4.3.4. أسئلة متقدمة شائعة عن Geography
- 4.3.4.1. هل تُجرى الحسابات على الكرة أم على الإهليلج (spheroid)؟
- 4.3.4.2. ماذا عن خط التاريخ الدولي والقطبين؟
- 4.3.4.3. ما أطول قوس يمكن معالجته؟
- 4.3.4.4. لماذا يكون حساب مساحة أوروبا / روسيا / أدخل هنا منطقة جغرافية كبيرة بطيئًا جدًا؟
|
4.3.4.1. |
هل تُجرى الحسابات على الكرة أم على الإهليلج (spheroid)؟ |
|
افتراضيًا، تُجرى جميع حسابات المسافة والمساحة على الإهليلج. وستجد أن نتائج الحسابات في المناطق المحلية تتطابق جيدًا مع النتائج المستوية المحلية في الإسقاطات المحلية الجيدة. وفي المناطق الأوسع، تكون الحسابات الإهليلجية أدق من أي حساب يُجرى على مستوى مُسقَط. توفّر جميع دوال geography خيار استخدام الحساب الكروي، بتعيين معامل منطقي (boolean) أخير إلى 'FALSE'. وهذا يسرّع الحسابات نوعًا ما، لا سيما في الحالات التي تكون فيها الأشكال الهندسية بسيطة جدًا. |
|
|
4.3.4.2. |
ماذا عن خط التاريخ الدولي والقطبين؟ |
|
لا تتضمن الحسابات كلها أي مفهوم لخط التاريخ أو القطبين، فالإحداثيات كروية (خط الطول/دائرة العرض)، لذا فإن الشكل الذي يعبر خط التاريخ لا يختلف، من منظور الحساب، عن أي شكل آخر. |
|
|
4.3.4.3. |
ما أطول قوس يمكن معالجته؟ |
|
نستخدم أقواس الدوائر العظمى بوصفها "خط الاستيفاء" بين نقطتين. وهذا يعني أن أي نقطتين تتصلان فعليًا بطريقتين، بحسب الاتجاه الذي تسلكه على الدائرة العظمى. وتفترض شيفرتنا كلها أن النقطتين متصلتان بـ*أقصر* المسارين على الدائرة العظمى. ونتيجة لذلك، لن تُنمذج الأشكال التي تحتوي على أقواس تزيد على 180 درجة نمذجةً صحيحة. |
|
|
4.3.4.4. |
لماذا يكون حساب مساحة أوروبا / روسيا / أدخل هنا منطقة جغرافية كبيرة بطيئًا جدًا؟ |
|
لأن المضلع ضخم للغاية! فالمساحات الكبيرة سيئة لسببين: حدودها ضخمة، لذا يميل الفهرس إلى جلب المعلم أيًا كان الاستعلام الذي تنفّذه؛ وعدد رؤوسها ضخم، والاختبارات (المسافة، والاحتواء) يجب أن تمر على قائمة الرؤوس مرة واحدة على الأقل وأحيانًا N مرة (حيث N عدد رؤوس المعلم المرشّح الآخر). كما في GEOMETRY، نوصي عندما تكون لديك مضلعات كبيرة جدًا لكنك تنفّذ استعلامات في مناطق صغيرة، بأن "تُفكّك" بياناتك الهندسية إلى أجزاء أصغر حتى يتمكن الفهرس من الاستعلام عن أجزاء الكائن بفاعلية، ولا تضطر الاستعلامات إلى جلب الكائن كاملًا في كل مرة. يُرجى الرجوع إلى توثيق الدالة ST_Subdivide. فكونك *تستطيع* تخزين أوروبا كلها في مضلع واحد لا يعني أنه *ينبغي* لك ذلك. |
4.4. التحقق من صلاحية الأشكال الهندسية
يتوافق PostGIS مع مواصفة Simple Features الصادرة عن Open Geospatial Consortium (OGC). ويُعرّف هذا المعيار مفهومَي الشكل الهندسي البسيط والصالح. وتتيح هذه التعريفات لنموذج Simple Features تمثيل الكائنات المكانية بطريقة متسقة لا لبس فيها تدعم الحساب الفعّال. (ملاحظة: لمعياري OGC SF وSQL/MM التعريفات نفسها للبسيط والصالح.)
4.4.1. الشكل الهندسي البسيط
الشكل الهندسي البسيط هو الذي لا يحتوي على نقاط هندسية شاذة، مثل التقاطع الذاتي أو التماس الذاتي.
النقطة POINT بسيطة بطبيعتها بوصفها كائنًا هندسيًا صفري البعد.
تكون النقاط المتعددة MULTIPOINT بسيطة إذا لم تتساوَ أي إحداثيتين (POINT) فيها (أي لم تكن لهما قيم إحداثيات متطابقة).
يكون الخط LINESTRING بسيطًا إذا لم يمر بالنقطة نفسها مرتين، باستثناء نقطتَي الطرفين. وإذا تطابقت نقطتا طرفَي خط بسيط سُمّي مغلقًا وأُشير إليه بالحلقة الخطية (Linear Ring).
|
(a) و(c) خطان |
(a) |
(b) |
(c) |
(d) |
يكون الخط المتعدد MULTILINESTRING بسيطًا فقط إذا كانت جميع عناصره بسيطة، وكان التقاطع الوحيد بين أي عنصرين يقع في نقاط على حدود كلا العنصرين.
|
(e) و(f) خطوط متعددة |
(e) |
(f) |
(g) |
تتكوّن المضلعات POLYGON من حلقات خطية، لذا فالأشكال الهندسية المضلعية الصالحة بسيطة دائمًا.
لاختبار ما إذا كان شكل هندسي بسيطًا استخدم الدالة ST_IsSimple:
SELECT
ST_IsSimple('LINESTRING(0 0, 100 100)') AS straight,
ST_IsSimple('LINESTRING(0 0, 100 100, 100 0, 0 100)') AS crossing;
straight | crossing
----------+----------
t | f
بوجه عام، لا تشترط دوال PostGIS أن تكون الوسائط الهندسية بسيطة. وتُستخدم البساطة أساسًا قاعدةً لتعريف الصلاحية الهندسية. وهي أيضًا شرط لبعض أنواع نماذج البيانات المكانية (فمثلًا كثيرًا ما تمنع الشبكات الخطية الخطوط المتقاطعة). ويمكن جعل النقاط المتعددة والأشكال الخطية بسيطة باستخدام ST_UnaryUnion.
4.4.2. الشكل الهندسي الصالح
تنطبق صلاحية الأشكال الهندسية أساسًا على الأشكال ثنائية الأبعاد (POLYGON وMULTIPOLYGON). وتُعرَّف الصلاحية بقواعد تتيح للأشكال المضلعية نمذجة المساحات المستوية دون لبس.
يكون المضلع POLYGON صالحًا إذا:
-
كانت حلقات حدود المضلع (الحلقة الخارجية للغلاف والحلقات الداخلية للثقوب) بسيطة (لا تتقاطع ولا تلامس نفسها). ولهذا لا يمكن أن يحتوي المضلع على خطوط قطع أو نتوءات أو عُرى. وهذا يعني أن ثقوب المضلع يجب أن تُمثَّل بحلقات داخلية، لا بملامسة الحلقة الخارجية لنفسها (ما يُسمى "الثقب المقلوب").
-
لم تتقاطع حلقات الحدود
-
جاز أن تتلامس حلقات الحدود في نقاط ولكن تماسًّا فقط (أي ليس على امتداد خط)
-
كانت الحلقات الداخلية محتواة في الحلقة الخارجية
-
كان داخل المضلع متصلًا اتصالًا بسيطًا (أي يجب ألا تتلامس الحلقات بطريقة تقسم المضلع إلى أكثر من جزء)
|
(h) و(i) مضلعان |
(h) |
(i) |
(j) |
(k) |
(l) |
(m) |
يكون المضلع المتعدد MULTIPOLYGON صالحًا إذا:
-
كانت مضلعاته
POLYGONالعناصر صالحة -
لم تتداخل العناصر (أي يجب ألا تتقاطع دواخلها)
-
لم تتلامس العناصر إلا في نقاط (أي ليس على امتداد خط)
|
(n) مضلع متعدد |
(n) |
(o) |
(p) |
تعني هذه القواعد أن الأشكال المضلعية الصالحة بسيطة أيضًا.
بالنسبة إلى الأشكال الخطية، فإن قاعدة الصلاحية الوحيدة هي أن تحتوي الخطوط LINESTRING على نقطتين على الأقل وأن يكون طولها غير صفري (أو بعبارة مكافئة، أن تحتوي على نقطتين متمايزتين على الأقل). لاحظ أن الخطوط غير البسيطة (المتقاطعة ذاتيًا) صالحة.
SELECT
ST_IsValid('LINESTRING(0 0, 1 1)') AS len_nonzero,
ST_IsValid('LINESTRING(0 0, 0 0, 0 0)') AS len_zero,
ST_IsValid('LINESTRING(10 10, 150 150, 180 50, 20 130)') AS self_int;
len_nonzero | len_zero | self_int
-------------+----------+----------
t | f | t
لا توجد قواعد صلاحية للأشكال الهندسية POINT وMULTIPOINT.
4.4.3. إدارة الصلاحية
يسمح PostGIS بإنشاء الأشكال الهندسية الصالحة وغير الصالحة وتخزينها. ويتيح ذلك اكتشاف الأشكال غير الصالحة ووسمها أو إصلاحها. وهناك أيضًا حالات تكون فيها قواعد الصلاحية في OGC أشد صرامة مما هو مرغوب (ومن أمثلة ذلك الخطوط ذات الطول الصفري والمضلعات ذات الثقوب المقلوبة).
تعتمد كثير من الدوال التي يوفّرها PostGIS على افتراض أن الوسائط الهندسية صالحة. فمثلًا لا معنى لحساب مساحة مضلع فيه ثقب معرّف خارج المضلع، أو لبناء مضلع من خط حدود غير بسيط. ويتيح افتراض صلاحية المدخلات الهندسية للدوال العمل بكفاءة أكبر، لأنها لا تحتاج إلى التحقق من السلامة الطوبولوجية. (ومن الاستثناءات البارزة أن الخطوط ذات الطول الصفري والمضلعات ذات الانقلابات تُعالَج عمومًا معالجة صحيحة.) كما أن معظم دوال PostGIS تُنتج أشكالًا هندسية صالحة إذا كانت المدخلات صالحة. وهذا يتيح ربط دوال PostGIS بعضها ببعض بأمان.
إذا واجهت رسائل خطأ غير متوقعة عند استدعاء دوال PostGIS (مثل "GEOS Intersection() threw an error!")، فعليك أولًا التأكد من صلاحية وسائط الدالة. فإن لم تكن صالحة، ففكّر في استخدام إحدى التقنيات أدناه لضمان صلاحية البيانات التي تعالجها.
|
|
|
إذا أبلغت دالة عن خطأ مع مدخلات صالحة، فربما تكون قد وجدت خطأً في PostGIS أو في إحدى المكتبات التي يستخدمها، وعليك الإبلاغ عن ذلك لمشروع PostGIS. ويصح الأمر نفسه إذا أعادت دالة من دوال PostGIS شكلًا هندسيًا غير صالح لمدخلات صالحة. |
لاختبار ما إذا كان شكل هندسي صالحًا استخدم الدالة ST_IsValid:
SELECT ST_IsValid('POLYGON ((20 180, 180 180, 180 20, 20 20, 20 180))');
-----------------
t
توفّر الدالة ST_IsValidDetail معلومات عن طبيعة عدم صلاحية الشكل الهندسي وموقعها:
SELECT valid, reason, ST_AsText(location) AS location
FROM ST_IsValidDetail('POLYGON ((20 20, 120 190, 50 190, 170 50, 20 20))') AS t;
valid | reason | location
-------+-------------------+---------------------------------------------
f | Self-intersection | POINT(91.51162790697674 141.56976744186045)
في بعض الحالات يُستحسن تصحيح الأشكال الهندسية غير الصالحة تلقائيًا. استخدم الدالة ST_MakeValid لذلك. (ST_MakeValid مثال على دالة مكانية تسمح فعلًا بمدخلات غير صالحة!)
افتراضيًا، لا يتحقق PostGIS من الصلاحية عند تحميل الأشكال الهندسية، لأن اختبار الصلاحية قد يستغرق وقت معالجة طويلًا للأشكال المعقدة. فإن لم تكن تثق بمصادر بياناتك، فيمكنك فرض التحقق من الصلاحية على جداولك بإضافة قيد تحقق (check constraint):
ALTER TABLE mytable
ADD CONSTRAINT geometry_valid_check
CHECK (ST_IsValid(geom));
4.5. الأنظمة المرجعية المكانية
يُعرّف النظام المرجعي المكاني (SRS) (ويُسمى أيضًا النظام المرجعي للإحداثيات (CRS)) كيفية إسناد الأشكال الهندسية إلى مواقع على سطح الأرض. وهناك ثلاثة أنواع من SRS:
-
يستخدم SRS الجيوديسي إحداثيات زاوية (خط الطول ودائرة العرض) تقابل سطح الأرض مباشرة.
-
يستخدم SRS المُسقَط تحويل إسقاط رياضيًا "لتسطيح" سطح الأرض الإهليلجي على مستوى. وهو يعيّن إحداثيات المواقع بطريقة تتيح القياس المباشر لكميات مثل المسافة والمساحة والزاوية. ونظام الإحداثيات ديكارتي، أي إن له نقطة أصل محددة ومحورين متعامدين (موجّهين عادةً نحو الشمال والشرق). ويستخدم كل SRS مُسقَط وحدة طول معلنة (الأمتار أو الأقدام عادةً). وقد يكون نطاق تطبيق SRS المُسقَط محدودًا لتجنب التشوّه وللبقاء ضمن حدود الإحداثيات المعرّفة.
-
SRS المحلي نظام إحداثيات ديكارتي غير مُسنَد إلى سطح الأرض. ويُحدَّد في PostGIS بقيمة SRID تساوي 0.
هناك أنظمة مرجعية مكانية كثيرة ومختلفة قيد الاستخدام. والأنظمة الشائعة منها موحّدة في قاعدة بيانات EPSG التابعة لمجموعة European Petroleum Survey Group. وتيسيرًا للأمر، يشير PostGIS (وكثير من الأنظمة المكانية الأخرى) إلى تعريفات SRS باستخدام معرّف عددي صحيح يُسمى SRID.
يرتبط الشكل الهندسي بنظام مرجعي مكاني عبر قيمة SRID الخاصة به، والتي يُوصل إليها بالدالة ST_SRID. ويمكن تعيين SRID للشكل الهندسي باستخدام ST_SetSRID. وتسمح بعض دوال إنشاء الأشكال الهندسية بتزويد SRID (مثل ST_Point وST_MakeEnvelope). وتدعم صيغة EWKT قيم SRID بالبادئة SRID=n;.
تتطلب الدوال المكانية التي تعالج أزواجًا من الأشكال الهندسية (مثل دوال التراكب والعلاقات) أن تكون الأشكال الهندسية المدخلة في النظام المرجعي المكاني نفسه (أي لها SRID نفسه). ويمكن تحويل البيانات الهندسية إلى نظام مرجعي مكاني مختلف باستخدام ST_Transform وST_TransformPipeline. والأشكال الهندسية التي تُعيدها الدوال لها SRS نفسه الذي للأشكال المدخلة.
4.5.1. الجدول SPATIAL_REF_SYS
الجدول SPATIAL_REF_SYS الذي يستخدمه PostGIS جدول قاعدة بيانات متوافق مع OGC يُعرّف الأنظمة المرجعية المكانية المتاحة. ويحتوي على أرقام SRID وأوصاف نصية لأنظمة الإحداثيات.
تعريف الجدول spatial_ref_sys هو:
CREATE TABLE spatial_ref_sys ( srid INTEGER NOT NULL PRIMARY KEY, auth_name VARCHAR(256), auth_srid INTEGER, srtext VARCHAR(2048), proj4text VARCHAR(2048) )
الأعمدة هي:
-
srid -
رمز عددي صحيح يعرّف النظام المرجعي المكاني (SRS) تعريفًا فريدًا داخل قاعدة البيانات.
-
auth_name -
اسم المعيار أو هيئة المعايير المستشهد بها لهذا النظام المرجعي. فمثلًا "EPSG" قيمة صالحة لـ
auth_name. -
auth_srid -
معرّف النظام المرجعي المكاني كما تعرّفه الهيئة المذكورة في
auth_name. وفي حالة EPSG، هذا هو رمز EPSG. -
srtext -
تمثيل Well-Known Text للنظام المرجعي المكاني. ومن أمثلة تمثيل SRS بصيغة WKT:
PROJCS["NAD83 / UTM Zone 10N", GEOGCS["NAD83", DATUM["North_American_Datum_1983", SPHEROID["GRS 1980",6378137,298.257222101] ], PRIMEM["Greenwich",0], UNIT["degree",0.0174532925199433] ], PROJECTION["Transverse_Mercator"], PARAMETER["latitude_of_origin",0], PARAMETER["central_meridian",-123], PARAMETER["scale_factor",0.9996], PARAMETER["false_easting",500000], PARAMETER["false_northing",0], UNIT["metre",1] ]لمناقشة WKT الخاصة بـ SRS، راجع معيار OGC Well-known text representation of coordinate reference systems.
-
proj4text -
يستخدم PostGIS مكتبة PROJ لتوفير قدرات تحويل الإحداثيات. ويحتوي العمود
proj4textعلى سلسلة تعريف الإحداثيات في PROJ لـ SRID معيّن. على سبيل المثال:+proj=utm +zone=10 +ellps=clrk66 +datum=NAD27 +units=m
لمزيد من المعلومات راجع موقع PROJ. ويحتوي الملف
spatial_ref_sys.sqlعلى تعريفاتsrtextوproj4textلجميع إسقاطات EPSG.
عند استرجاع تعريفات الأنظمة المرجعية المكانية لاستخدامها في التحويلات، يتّبع PostGIS الاستراتيجية التالية:
-
إذا وُجدت
auth_nameوauth_srid(غير NULL) فاستخدم SRS الخاص بـ PROJ المبني على هذين المدخلين (إن وُجد). -
إذا وُجد
srtextفأنشئ SRS باستخدامه، إن أمكن. -
إذا وُجد
proj4textفأنشئ SRS باستخدامه، إن أمكن.
4.5.2. الأنظمة المرجعية المكانية المعرّفة من المستخدم
يحتوي الجدول spatial_ref_sys في PostGIS على أكثر من 3000 من تعريفات الأنظمة المرجعية المكانية الأكثر شيوعًا التي تتعامل معها مكتبة الإسقاط PROJ. لكن هناك أنظمة إحداثيات كثيرة لا يحتويها. ويمكنك إضافة تعريفات SRS إلى الجدول إذا توفرت لديك المعلومات اللازمة عن النظام المرجعي المكاني. أو يمكنك تعريف نظامك المرجعي المكاني المخصص إذا كنت على دراية ببُنى PROJ. وتذكّر أن معظم الأنظمة المرجعية المكانية إقليمية ولا معنى لها عند استخدامها خارج الحدود التي وُضعت لها.
من الموارد المفيدة للعثور على أنظمة مرجعية مكانية غير معرّفة في المجموعة الأساسية http://spatialreference.org/
من الأنظمة المرجعية المكانية الشائعة الاستخدام: 4326 - WGS 84 Long Lat، و4269 - NAD 83 Long Lat، و3395 - WGS 84 World Mercator، و2163 - US National Atlas Equal Area، ونطاقات WGS84 UTM الستون. وتُعد نطاقات UTM من أنسب الأنظمة للقياس، لكنها لا تغطي إلا مناطق بعرض 6 درجات. (لتحديد نطاق UTM المناسب لمنطقة اهتمامك، راجع الدالة المساعدة utmzone المكتوبة بـ plpgsql في PostGIS.)
تستخدم الولايات الأمريكية الأنظمة المرجعية المكانية State Plane (القائمة على المتر أو القدم) - ويوجد عادةً نظام أو نظامان لكل ولاية. ومعظم الأنظمة القائمة على المتر موجودة في المجموعة الأساسية، لكن كثيرًا من الأنظمة القائمة على القدم أو التي أنشأتها ESRI يجب نسخها من spatialreference.org.
بل يمكنك تعريف أنظمة إحداثيات غير قائمة على الأرض، مثل Mars 2000. ونظام إحداثيات المريخ هذا غير مستوٍ (فهو بالدرجات الإهليلجية)، لكن يمكنك استخدامه مع النوع geography للحصول على قياسات الطول والقرب بالأمتار بدلًا من الدرجات.
فيما يلي مثال على تحميل نظام إحداثيات مخصص باستخدام SRID غير مُعيَّن وتعريف PROJ لإسقاط Lambert Conformal متمركز على الولايات المتحدة:
INSERT INTO spatial_ref_sys (srid, proj4text) VALUES ( 990000, '+proj=lcc +lon_0=-95 +lat_0=25 +lat_1=25 +lat_2=25 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs' );
4.6. الجداول المكانية
4.6.1. إنشاء جدول مكاني
يمكنك إنشاء جدول لتخزين البيانات الهندسية باستخدام تعليمة SQL CREATE TABLE مع عمود من النوع geometry. ينشئ المثال التالي جدولًا فيه عمود geometry يخزّن خطوطًا ثنائية الأبعاد (XY) في نظام الإحداثيات BC-Albers (SRID 3005):
CREATE TABLE roads (
id SERIAL PRIMARY KEY,
name VARCHAR(64),
geom geometry(LINESTRING,3005)
);
يدعم النوع geometry مُعدِّلَي نوع اختياريين:
-
مُعدِّل النوع المكاني يقيّد صنف الأشكال وأبعادها المسموح بها في العمود. ويمكن أن تكون القيمة أيًا من الأنواع الفرعية للأشكال الهندسية المدعومة (مثل POINT وLINESTRING وPOLYGON وMULTIPOINT وMULTILINESTRING وMULTIPOLYGON وGEOMETRYCOLLECTION وغيرها). ويدعم المُعدِّل تقييد أبعاد الإحداثيات بإضافة اللواحق: Z وM وZM. فمثلًا المُعدِّل 'LINESTRINGM' لا يسمح إلا بخطوط ثلاثية الأبعاد، ويعامل البعد الثالث بوصفه قياسًا. وبالمثل، يتطلب 'POINTZM' بيانات رباعية الأبعاد (XYZM).
-
مُعدِّل SRID يقيّد SRID النظام المرجعي المكاني برقم معيّن. وإذا حُذف، تكون القيمة الافتراضية لـ SRID هي 0.
أمثلة على إنشاء جداول بأعمدة geometry:
-
إنشاء جدول يحمل أي نوع من الأشكال الهندسية مع SRID الافتراضي:
CREATE TABLE geoms(gid serial PRIMARY KEY, geom geometry );
-
إنشاء جدول بأشكال POINT ثنائية الأبعاد مع SRID الافتراضي:
CREATE TABLE pts(gid serial PRIMARY KEY, geom geometry(POINT) );
-
إنشاء جدول بنقاط POINT ثلاثية الأبعاد (XYZ) مع SRID صريح قيمته 3005:
CREATE TABLE pts(gid serial PRIMARY KEY, geom geometry(POINTZ,3005) );
-
إنشاء جدول بخطوط LINESTRING رباعية الأبعاد (XYZM) مع SRID الافتراضي:
CREATE TABLE lines(gid serial PRIMARY KEY, geom geometry(LINESTRINGZM) );
-
إنشاء جدول بمضلعات POLYGON ثنائية الأبعاد مع SRID 4267 (NAD 1927 خط الطول/دائرة العرض):
CREATE TABLE polys(gid serial PRIMARY KEY, geom geometry(POLYGON,4267) );
يمكن أن يحتوي الجدول على أكثر من عمود geometry واحد. ويمكن تحديد ذلك عند إنشاء الجدول، أو إضافة عمود باستخدام تعليمة SQL ALTER TABLE. يضيف هذا المثال عمودًا يمكنه حمل خطوط ثلاثية الأبعاد:
ALTER TABLE roads ADD COLUMN geom2 geometry(LINESTRINGZ,4326);
4.6.2. العرض GEOMETRY_COLUMNS
تُعرّف مواصفة OGC Simple Features Specification for SQL جدول البيانات الوصفية GEOMETRY_COLUMNS لوصف بنية الجداول الهندسية. وفي PostGIS يكون geometry_columns عرضًا (view) يقرأ من جداول فهرس نظام قاعدة البيانات. وهذا يضمن أن تكون معلومات البيانات الوصفية المكانية متسقة دائمًا مع الجداول والعروض المعرّفة حاليًا. وبنية العرض هي:
\d geometry_columns
View "public.geometry_columns"
Column | Type | Modifiers
-------------------+------------------------+-----------
f_table_catalog | character varying(256) |
f_table_schema | character varying(256) |
f_table_name | character varying(256) |
f_geometry_column | character varying(256) |
coord_dimension | integer |
srid | integer |
type | character varying(30) |
الأعمدة هي:
-
f_table_catalog, f_table_schema, f_table_name -
الاسم المؤهَّل بالكامل لجدول المعالم الذي يحتوي على عمود geometry. لا يوجد في PostgreSQL ما يقابل "catalog" لذا يُترك ذلك العمود فارغًا. وبالنسبة إلى "schema" يُستخدم اسم المخطط (schema) في PostgreSQL (و
publicهو الافتراضي). -
f_geometry_column -
اسم عمود geometry في جدول المعالم.
-
coord_dimension -
بُعد الإحداثيات (2 أو 3 أو 4) للعمود.
-
srid -
معرّف النظام المرجعي المكاني المستخدم للأشكال الهندسية في هذا الجدول. وهو مرجع مفتاح أجنبي إلى الجدول
spatial_ref_sys(راجع قسم 4.5.1, “الجدول SPATIAL_REF_SYS”). -
type -
نوع الكائن المكاني. لتقييد العمود المكاني بنوع واحد، استخدم أحد الأنواع: POINT أو LINESTRING أو POLYGON أو MULTIPOINT أو MULTILINESTRING أو MULTIPOLYGON أو GEOMETRYCOLLECTION أو نسخها المقابلة XYM: POINTM أو LINESTRINGM أو POLYGONM أو MULTIPOINTM أو MULTILINESTRINGM أو MULTIPOLYGONM أو GEOMETRYCOLLECTIONM. وللمجموعات غير المتجانسة (مختلطة الأنواع)، يمكنك استخدام "GEOMETRY" نوعًا.
4.6.3. تسجيل أعمدة Geometry يدويًا
من الحالات التي قد تحتاج فيها إلى ذلك حالتا عروض SQL (views) والإدراج المجمّع. ففي حالة الإدراج المجمّع، يمكنك تصحيح التسجيل في الجدول geometry_columns بتقييد العمود أو بتنفيذ alter table. أما في العروض، فيمكنك الكشف عن العمود باستخدام عملية CAST. لاحظ أنه إذا كان عمودك قائمًا على typmod، فإن عملية الإنشاء ستسجّله تسجيلًا صحيحًا، فلا حاجة إلى فعل أي شيء. كما أن العروض التي لم تُطبَّق فيها أي دالة مكانية على الشكل الهندسي ستُسجَّل بالطريقة نفسها التي سُجّل بها عمود geometry في الجدول الأساسي.
-- Lets say you have a view created like this
CREATE VIEW public.vwmytablemercator AS
SELECT gid, ST_Transform(geom, 3395) As geom, f_name
FROM public.mytable;
-- For it to register correctly
-- You need to cast the geometry
--
DROP VIEW public.vwmytablemercator;
CREATE VIEW public.vwmytablemercator AS
SELECT gid, ST_Transform(geom, 3395)::geometry(Geometry, 3395) As geom, f_name
FROM public.mytable;
-- If you know the geometry type for sure is a 2D POLYGON then you could do
DROP VIEW public.vwmytablemercator;
CREATE VIEW public.vwmytablemercator AS
SELECT gid, ST_Transform(geom,3395)::geometry(Polygon, 3395) As geom, f_name
FROM public.mytable;
--Lets say you created a derivative table by doing a bulk insert
SELECT poi.gid, poi.geom, citybounds.city_name
INTO myschema.my_special_pois
FROM poi INNER JOIN citybounds ON ST_Intersects(citybounds.geom, poi.geom);
-- Create 2D index on new table
CREATE INDEX idx_myschema_myspecialpois_geom_gist
ON myschema.my_special_pois USING gist(geom);
-- If your points are 3D points or 3M points,
-- then you might want to create an nd index instead of a 2D index
CREATE INDEX my_special_pois_geom_gist_nd
ON my_special_pois USING gist(geom gist_geometry_ops_nd);
-- To manually register this new table's geometry column in geometry_columns.
-- Note it will also change the underlying structure of the table to
-- to make the column typmod based.
SELECT populate_geometry_columns('myschema.my_special_pois'::regclass);
-- If you are using PostGIS 2.0 and for whatever reason, you
-- you need the constraint based definition behavior
-- (such as case of inherited tables where all children do not have the same type and srid)
-- set optional use_typmod argument to false
SELECT populate_geometry_columns('myschema.my_special_pois'::regclass, false);
مع أن الطريقة القديمة القائمة على القيود لا تزال مدعومة، فإن عمود geometry القائم على القيود والمستخدم مباشرةً في عرض (view) لن يُسجَّل تسجيلًا صحيحًا في geometry_columns، بخلاف العمود القائم على typmod. في هذا المثال نعرّف عمودًا باستخدام typmod وآخر باستخدام القيود.
CREATE TABLE pois_ny(gid SERIAL PRIMARY KEY, poi_name text, cat text, geom geometry(POINT,4326));
SELECT AddGeometryColumn('pois_ny', 'geom_2160', 2160, 'POINT', 2, false);
إذا نفّذنا في psql
\d pois_ny;
نلاحظ أنهما معرّفان بطريقتين مختلفتين -- أحدهما بـ typmod والآخر بقيد
Table "public.pois_ny"
Column | Type | Modifiers
-----------+-----------------------+------------------------------------------------------
gid | integer | not null default nextval('pois_ny_gid_seq'::regclass)
poi_name | text |
cat | character varying(20) |
geom | geometry(Point,4326) |
geom_2160 | geometry |
Indexes:
"pois_ny_pkey" PRIMARY KEY, btree (gid)
Check constraints:
"enforce_dims_geom_2160" CHECK (st_ndims(geom_2160) = 2)
"enforce_geotype_geom_2160" CHECK (geometrytype(geom_2160) = 'POINT'::text
OR geom_2160 IS NULL)
"enforce_srid_geom_2160" CHECK (st_srid(geom_2160) = 2160)
في geometry_columns، يُسجَّل كلاهما تسجيلًا صحيحًا
SELECT f_table_name, f_geometry_column, srid, type
FROM geometry_columns
WHERE f_table_name = 'pois_ny';
f_table_name | f_geometry_column | srid | type -------------+-------------------+------+------- pois_ny | geom | 4326 | POINT pois_ny | geom_2160 | 2160 | POINT
لكن -- إذا أنشأنا عرضًا (view) كهذا
CREATE VIEW vw_pois_ny_parks AS
SELECT *
FROM pois_ny
WHERE cat='park';
SELECT f_table_name, f_geometry_column, srid, type
FROM geometry_columns
WHERE f_table_name = 'vw_pois_ny_parks';
يُسجَّل عمود العرض geom القائم على typmod تسجيلًا صحيحًا، أما القائم على القيد فلا.
f_table_name | f_geometry_column | srid | type ------------------+-------------------+------+---------- vw_pois_ny_parks | geom | 4326 | POINT vw_pois_ny_parks | geom_2160 | 0 | GEOMETRY
قد يتغيّر هذا في الإصدارات المستقبلية من PostGIS، لكن حاليًا لإجبار عمود العرض القائم على القيد على التسجيل الصحيح، عليك فعل ما يلي:
DROP VIEW vw_pois_ny_parks;
CREATE VIEW vw_pois_ny_parks AS
SELECT gid, poi_name, cat,
geom,
geom_2160::geometry(POINT,2160) As geom_2160
FROM pois_ny
WHERE cat = 'park';
SELECT f_table_name, f_geometry_column, srid, type
FROM geometry_columns
WHERE f_table_name = 'vw_pois_ny_parks';
f_table_name | f_geometry_column | srid | type ------------------+-------------------+------+------- vw_pois_ny_parks | geom | 4326 | POINT vw_pois_ny_parks | geom_2160 | 2160 | POINT
4.7. تحميل البيانات المكانية
بعد إنشاء جدول مكاني تصبح جاهزًا لرفع البيانات المكانية إلى قاعدة البيانات. توجد طريقتان مدمجتان لإدخال البيانات المكانية إلى قاعدة بيانات PostGIS/PostgreSQL: استخدام تعليمات SQL منسّقة أو استخدام مُحمِّل Shapefile.
4.7.1. استخدام SQL لتحميل البيانات
إذا أمكن تحويل البيانات المكانية إلى تمثيل نصي (WKT أو WKB)، فقد يكون استخدام SQL أسهل طريقة لإدخال البيانات إلى PostGIS. يمكن تحميل البيانات دفعةً واحدة إلى PostGIS/PostgreSQL بتحميل ملف نصي يتضمن تعليمات INSERT في SQL باستخدام أداة SQL المسماة psql.
قد يبدو ملف تحميل SQL (مثل roads.sql) على النحو الآتي:
BEGIN; INSERT INTO roads (road_id, roads_geom, road_name) VALUES (1,'LINESTRING(191232 243118,191108 243242)','Jeff Rd'); INSERT INTO roads (road_id, roads_geom, road_name) VALUES (2,'LINESTRING(189141 244158,189265 244817)','Geordie Rd'); INSERT INTO roads (road_id, roads_geom, road_name) VALUES (3,'LINESTRING(192783 228138,192612 229814)','Paul St'); INSERT INTO roads (road_id, roads_geom, road_name) VALUES (4,'LINESTRING(189412 252431,189631 259122)','Graeme Ave'); INSERT INTO roads (road_id, roads_geom, road_name) VALUES (5,'LINESTRING(190131 224148,190871 228134)','Phil Tce'); INSERT INTO roads (road_id, roads_geom, road_name) VALUES (6,'LINESTRING(198231 263418,198213 268322)','Dave Cres'); COMMIT;
يمكن تحميل ملف SQL إلى PostgreSQL باستخدام psql:
psql -d [database] -f roads.sql
4.7.2. استخدام مُحمِّل Shapefile
يحوّل مُحمِّل البيانات shp2pgsql ملفات Shapefile إلى SQL مناسب للإدراج في قاعدة بيانات PostGIS/PostgreSQL بصيغة geometry أو geography. للمُحمِّل عدة أوضاع تشغيل تُختار بواسطة خيارات سطر الأوامر.
توجد أيضًا واجهة رسومية shp2pgsql-gui تتضمن معظم خيارات مُحمِّل سطر الأوامر. قد تكون أسهل استخدامًا للتحميل لمرة واحدة دون نصوص برمجية أو إذا كنت جديدًا على PostGIS. ويمكن أيضًا إعدادها كإضافة لـ PgAdminIII.
- (c|a|d|p) هذه خيارات متنافية:
-
-
-c -
يُنشئ جدولًا جديدًا ويملؤه من ملف Shapefile. هذا هو الوضع الافتراضي.
-
-a -
يُلحق البيانات من ملف Shapefile بجدول قاعدة البيانات. لاحظ أنه لاستخدام هذا الخيار لتحميل عدة ملفات، يجب أن تكون للملفات السمات نفسها وأنواع البيانات نفسها.
-
-d -
يحذف جدول قاعدة البيانات قبل إنشاء جدول جديد بالبيانات الموجودة في ملف Shapefile.
-
-p -
يُنتج فقط شيفرة SQL لإنشاء الجدول دون إضافة أي بيانات فعلية. يمكن استخدام ذلك إذا احتجت إلى الفصل التام بين خطوتي إنشاء الجدول وتحميل البيانات.
-
-
-? -
عرض شاشة المساعدة.
-
-D -
استخدام صيغة "dump" الخاصة بـ PostgreSQL لبيانات الإخراج. يمكن دمج ذلك مع -a و-c و-d. تحميلها أسرع بكثير من صيغة SQL الافتراضية "insert". استخدمها لمجموعات البيانات الكبيرة جدًا.
-
-s [<FROM_SRID>:]<SRID> -
يُنشئ جداول geometry ويملؤها بقيمة SRID المحددة. ويحدد اختياريًا أن ملف Shapefile المُدخل يستخدم FROM_SRID المُعطى، وفي هذه الحالة يُعاد إسقاط الأشكال الهندسية إلى SRID الهدف.
-
-k -
الحفاظ على حالة أحرف المعرّفات (العمود والمخطط والسمات). لاحظ أن السمات في Shapefile كلها بأحرف كبيرة.
-
-i -
فرض تحويل جميع الأعداد الصحيحة إلى أعداد صحيحة قياسية بحجم 32 بت، وعدم إنشاء bigint بحجم 64 بت، حتى لو بدا أن توقيع ترويسة DBF يستدعي ذلك.
-
-I -
إنشاء فهرس GiST على عمود geometry.
-
-m -
-m
a_file_nameتحديد ملف يحتوي على مجموعة من التعيينات بين أسماء الأعمدة (الطويلة) وأسماء أعمدة DBF المكوّنة من 10 أحرف. محتوى الملف سطر واحد أو أكثر، في كل منها اسمان يفصل بينهما فراغ دون فراغات في البداية أو النهاية. على سبيل المثال:COLUMNNAME DBFFIELD1 AVERYLONGCOLUMNNAME DBFFIELD2
-
-S -
إنشاء أشكال هندسية بسيطة بدلًا من أشكال MULTI. لن ينجح ذلك إلا إذا كانت جميع الأشكال الهندسية مفردة فعليًا (أي MULTIPOLYGON بغلاف واحد، أو MULTIPOINT برأس واحد).
-
-t <dimensionality> -
فرض عدد أبعاد محدد على الشكل الهندسي الناتج. استخدم السلاسل الآتية للإشارة إلى عدد الأبعاد: 2D، 3DZ، 3DM، 4D.
إذا كان عدد أبعاد المُدخل أقل من المحدد، فستُملأ تلك الأبعاد في الناتج بأصفار. وإذا كان عدد أبعاد المُدخل أكثر من المحدد، فستُزال الأبعاد غير المرغوبة.
-
-w -
الإخراج بصيغة WKT بدلًا من WKB. لاحظ أن ذلك قد يُسبب انحرافًا في الإحداثيات بسبب فقدان الدقة.
-
-e -
تنفيذ كل تعليمة على حدة دون استخدام معاملة. يتيح ذلك تحميل معظم البيانات السليمة عند وجود بعض الأشكال الهندسية التالفة التي تُولّد أخطاء. لاحظ أنه لا يمكن استخدام ذلك مع الخيار -D لأن صيغة "dump" تستخدم معاملة دائمًا.
-
-W <encoding> -
تحديد ترميز بيانات الإدخال (ملف dbf). عند استخدامه، تُحوَّل جميع سمات ملف dbf من الترميز المحدد إلى UTF8. سيحتوي ناتج SQL على الأمر
SET CLIENT_ENCODING to UTF8، حتى يتمكن الخادم من إعادة التحويل من UTF8 إلى أي ترميز مُعَدّ لقاعدة البيانات داخليًا. -
-N <policy> -
سياسة التعامل مع الأشكال الهندسية الفارغة NULL (insert*,skip,abort)
-
-n -
-n استيراد ملف DBF فقط. إذا لم يكن لبياناتك ملف Shapefile مقابل، فسيتحول تلقائيًا إلى هذا الوضع ويحمّل ملف dbf فقط. لذا لا يلزم ضبط هذا الخيار إلا إذا كانت لديك مجموعة Shapefile كاملة وتريد بيانات السمات فقط دون الأشكال الهندسية.
-
-G -
استخدام النوع geography بدلًا من geometry (يتطلب بيانات خطوط طول/عرض) بنظام WGS84 للطول والعرض (SRID=4326)
-
-T <tablespace> -
تحديد مساحة الجداول (tablespace) للجدول الجديد. ستظل الفهارس تستخدم مساحة الجداول الافتراضية ما لم يُستخدم الخيار -X أيضًا. يتضمن توثيق PostgreSQL شرحًا جيدًا لمتى تُستخدم مساحات جداول مخصصة.
-
-X <tablespace> -
تحديد مساحة الجداول (tablespace) لفهارس الجدول الجديد. ينطبق ذلك على فهرس المفتاح الأساسي، وعلى الفهرس المكاني GIST إذا استُخدم الخيار -I أيضًا.
-
-Z -
عند استخدام هذا الخيار، يمنع توليد تعليمات
ANALYZE. وبدون الخيار -Z (السلوك الافتراضي)، تُولَّد تعليماتANALYZE.
قد تبدو جلسة نموذجية تستخدم المُحمِّل لإنشاء ملف إدخال ثم تحميله على النحو الآتي:
# shp2pgsql -c -D -s 4269 -i -I shaperoads.shp myschema.roadstable > roads.sql # psql -d roadsdb -f roads.sql
يمكن إجراء التحويل والتحميل في خطوة واحدة باستخدام أنابيب UNIX:
# shp2pgsql shaperoads.shp myschema.roadstable | psql -d roadsdb
4.8. استخراج البيانات المكانية
يمكن استخراج البيانات المكانية من قاعدة البيانات باستخدام SQL أو مُفرِّغ Shapefile. يعرض القسم الخاص بـ SQL بعض الدوال المتاحة لإجراء المقارنات والاستعلامات على الجداول المكانية.
4.8.1. استخدام SQL لاستخراج البيانات
أبسط طريقة لاستخراج البيانات المكانية من قاعدة البيانات هي استخدام استعلام SQL SELECT لتحديد مجموعة البيانات المراد استخراجها وتفريغ الأعمدة الناتجة في ملف نصي قابل للتحليل:
db=# SELECT road_id, ST_AsText(road_geom) AS geom, road_name FROM roads;
road_id | geom | road_name
--------+-----------------------------------------+-----------
1 | LINESTRING(191232 243118,191108 243242) | Jeff Rd
2 | LINESTRING(189141 244158,189265 244817) | Geordie Rd
3 | LINESTRING(192783 228138,192612 229814) | Paul St
4 | LINESTRING(189412 252431,189631 259122) | Graeme Ave
5 | LINESTRING(190131 224148,190871 228134) | Phil Tce
6 | LINESTRING(198231 263418,198213 268322) | Dave Cres
7 | LINESTRING(218421 284121,224123 241231) | Chris Way
(6 rows)
ستحتاج أحيانًا إلى قيد ما لتقليل عدد السجلات المُعادة. في حالة القيود المبنية على السمات، استخدم صيغة SQL نفسها المستخدمة مع الجداول غير المكانية. أما في حالة القيود المكانية، فالدوال الآتية مفيدة:
-
ST_Intersects -
تُبيّن هذه الدالة ما إذا كان شكلان هندسيان يشتركان في أي حيز.
-
= -
يختبر هذا ما إذا كان شكلان هندسيان متطابقين هندسيًا. على سبيل المثال، ما إذا كان 'POLYGON((0 0,1 1,1 0,0 0))' هو نفسه 'POLYGON((0 0,1 1,1 0,0 0))' (وهو كذلك).
بعد ذلك يمكنك استخدام هذه العوامل في الاستعلامات. لاحظ أنه عند تحديد الأشكال الهندسية والصناديق في سطر أوامر SQL، يجب تحويل التمثيلات النصية صراحةً إلى أشكال هندسية باستخدام دالة. الرقم 312 نظام مرجعي مكاني وهمي يطابق بياناتنا. على سبيل المثال:
SELECT road_id, road_name FROM roads WHERE roads_geom='SRID=312;LINESTRING(191232 243118,191108 243242)'::geometry;
سيُعيد الاستعلام أعلاه السجل الوحيد من الجدول "ROADS_GEOM" الذي يساوي فيه الشكل الهندسي تلك القيمة.
للتحقق مما إذا كان بعض الطرق يمر في المنطقة المحددة بمضلع:
SELECT road_id, road_name FROM roads WHERE ST_Intersects(roads_geom, 'SRID=312;POLYGON((...))');
من المرجح أن يكون الاستعلام المكاني الأكثر شيوعًا هو الاستعلام "المبني على الإطار"، الذي تستخدمه برمجيات العميل، مثل متصفحات البيانات وتطبيقات الخرائط على الويب، لجلب بيانات بقدر "إطار خريطة" لعرضها.
عند استخدام العامل "&&"، يمكنك تحديد BOX3D أو GEOMETRY كعنصر للمقارنة. لكن عند تحديد GEOMETRY، سيُستخدم المستطيل المحيط به للمقارنة.
باستخدام كائن "BOX3D" للإطار، يبدو هذا الاستعلام على النحو الآتي:
SELECT ST_AsText(roads_geom) AS geom FROM roads WHERE roads_geom && ST_MakeEnvelope(191232, 243117,191232, 243119,312);
لاحظ استخدام SRID 312 لتحديد إسقاط الغلاف.
4.8.2. استخدام مُفرِّغ Shapefile
يتصل مُفرِّغ الجداول pgsql2shp بقاعدة البيانات ويحوّل جدولًا (قد يكون معرّفًا باستعلام) إلى ملف Shapefile. الصيغة الأساسية هي:
pgsql2shp [<options >] <database > [<schema >.]<table>
pgsql2shp [<options >] <database > <query>
خيارات سطر الأوامر هي:
-
-f <filename> -
كتابة الناتج إلى اسم ملف محدد.
-
-h <host> -
مضيف قاعدة البيانات المراد الاتصال به.
-
-p <port> -
المنفذ المراد الاتصال به على مضيف قاعدة البيانات.
-
-P <password> -
كلمة المرور المستخدمة عند الاتصال بقاعدة البيانات.
-
-u <user> -
اسم المستخدم المستخدم عند الاتصال بقاعدة البيانات.
-
-g <geometry column> -
في حالة الجداول التي تحتوي على عدة أعمدة geometry، عمود geometry المراد استخدامه عند كتابة ملف Shapefile.
-
-b -
استخدام مؤشر ثنائي (binary cursor). سيجعل ذلك العملية أسرع، لكنه لن يعمل إذا كانت أي سمة غير هندسية في الجدول تفتقر إلى تحويل إلى نص.
-
-r -
الوضع الخام. عدم حذف الحقل
gid، وعدم تهريب أسماء الأعمدة. -
-m filename -
إعادة تعيين المعرّفات إلى أسماء من عشرة أحرف. محتوى الملف أسطر في كل منها رمزان يفصل بينهما فراغ واحد دون فراغات في البداية أو النهاية: VERYLONGSYMBOL SHORTONE ANOTHERVERYLONGSYMBOL SHORTER إلخ.
4.9. الفهارس المكانية
تجعل الفهارس المكانية استخدام قاعدة بيانات مكانية لمجموعات البيانات الكبيرة ممكنًا. فبدون الفهرسة، يتطلب البحث عن المعالم مسحًا تسلسليًا لكل سجل في قاعدة البيانات. تُسرّع الفهرسة البحث بتنظيم البيانات في بنية يمكن اجتيازها بسرعة للعثور على السجلات المطابقة.
طريقة الفهرسة B-tree الشائعة الاستخدام لبيانات السمات ليست مفيدة كثيرًا للبيانات المكانية، لأنها لا تدعم تخزين البيانات والاستعلام عنها إلا في بُعد واحد. أما بيانات مثل geometry (ذات بُعدين أو أكثر) فتتطلب طريقة فهرسة تدعم استعلامات النطاق عبر جميع أبعاد البيانات. ومن المزايا الأساسية لـ PostgreSQL في معالجة البيانات المكانية أنها توفر عدة أنواع من طرق الفهرسة التي تعمل جيدًا مع البيانات متعددة الأبعاد: فهارس GiST وBRIN وSP-GiST.
-
تُقسّم فهارس GiST (شجرة البحث المعمّمة) البيانات إلى "أشياء في جانب واحد" و"أشياء متداخلة" و"أشياء تقع في الداخل"، ويمكن استخدامها على نطاق واسع من أنواع البيانات، بما فيها بيانات GIS. يستخدم PostGIS فهرس R-Tree مبنيًا فوق GiST لفهرسة البيانات المكانية. وGiST هي طريقة الفهرسة المكانية الأكثر شيوعًا وتنوعًا، وتوفر أداءً جيدًا جدًا للاستعلامات.
-
تعمل فهارس BRIN (فهرس نطاق الكتل) بتلخيص الامتداد المكاني لنطاقات من سجلات الجدول. ويجري البحث عبر مسح هذه النطاقات. لا تناسب BRIN إلا بعض أنواع البيانات (المرتبة مكانيًا، والتي تُحدَّث نادرًا أو لا تُحدَّث). لكنها توفر وقت إنشاء فهرس أسرع بكثير، وحجم فهرس أصغر بكثير.
-
SP-GiST (شجرة البحث المعمّمة المقسّمة مكانيًا) طريقة فهرسة عامة تدعم أشجار البحث المقسّمة مثل أشجار quad-tree وأشجار k-d وأشجار radix (tries).
تخزّن الفهارس المكانية المستطيل المحيط بالأشكال الهندسية فقط. تستخدم الاستعلامات المكانية الفهرس كمرشّح أولي لتحديد مجموعة الأشكال الهندسية التي يُحتمل أن تطابق شرط الاستعلام بسرعة. وتتطلب معظم الاستعلامات المكانية مرشّحًا ثانويًا يستخدم دالة شرط مكاني لاختبار شرط مكاني أكثر تحديدًا. لمزيد من المعلومات حول الاستعلام باستخدام الشروط المكانية، انظر قسم 5.2, “استخدام الفهارس المكانية”.
انظر أيضًا قسم الفهارس المكانية في ورشة عمل PostGIS، ودليل PostgreSQL.
4.9.1. فهارس GiST
GiST اختصار لـ "Generalized Search Tree" (شجرة البحث المعمّمة)، وهي شكل عام من الفهرسة للبيانات متعددة الأبعاد. يستخدم PostGIS فهرس R-Tree مبنيًا فوق GiST لفهرسة البيانات المكانية. وGiST هي طريقة الفهرسة المكانية الأكثر شيوعًا وتنوعًا، وتوفر أداءً جيدًا جدًا للاستعلامات. وتُستخدم تطبيقات أخرى لـ GiST لتسريع البحث في جميع أنواع بنى البيانات غير المنتظمة (مصفوفات الأعداد الصحيحة، والبيانات الطيفية، وغيرها) التي لا تناسبها فهرسة B-Tree العادية. لمزيد من المعلومات انظر دليل PostgreSQL.
حين يتجاوز جدول البيانات المكانية بضعة آلاف من الصفوف، ستحتاج إلى بناء فهرس لتسريع عمليات البحث المكاني في البيانات (ما لم تكن جميع عمليات بحثك مبنية على السمات، وفي هذه الحالة ستحتاج إلى بناء فهرس عادي على حقول السمات).
صيغة بناء فهرس GiST على عمود "geometry" هي كالآتي:
CREATE INDEX [indexname] ON [tablename] USING GIST ( [geometryfield] );
ستبني الصيغة أعلاه دائمًا فهرسًا ثنائي الأبعاد. للحصول على فهرس n-الأبعاد للنوع geometry، يمكنك إنشاؤه باستخدام هذه الصيغة:
CREATE INDEX [indexname] ON [tablename] USING GIST ([geometryfield] gist_geometry_ops_nd);
بناء فهرس مكاني عملية كثيفة الحساب. كما أنها تمنع الكتابة في جدولك طوال مدة الإنشاء، لذا قد ترغب في نظام الإنتاج في تنفيذها بطريقة أبطأ تراعي CONCURRENTLY:
CREATE INDEX CONCURRENTLY [indexname] ON [tablename] USING GIST ( [geometryfield] );
بعد بناء فهرس، يكون من المفيد أحيانًا إجبار PostgreSQL على جمع إحصاءات الجدول، التي تُستخدم لتحسين خطط الاستعلام:
VACUUM ANALYZE [table_name] [(column_name)];
4.9.2. فهارس BRIN
BRIN اختصار لـ "Block Range Index" (فهرس نطاق الكتل). وهي طريقة فهرسة عامة الغرض قُدّمت في PostgreSQL 9.5. BRIN طريقة فهرسة فاقدة (lossy)، أي أنها تتطلب تحققًا ثانويًا لتأكيد مطابقة السجل لشرط بحث معين (وهذا هو الحال في جميع الفهارس المكانية المتوفرة). توفر إنشاءً أسرع بكثير للفهرس وحجم فهرس أصغر بكثير، مع أداء قراءة معقول. والغرض الأساسي منها دعم فهرسة الجداول الكبيرة جدًا على الأعمدة التي ترتبط بموقعها الفعلي داخل الجدول. وإضافة إلى الفهرسة المكانية، يمكن لـ BRIN تسريع البحث في أنواع مختلفة من بنى بيانات السمات (الأعداد الصحيحة، والمصفوفات، وغيرها). لمزيد من المعلومات انظر دليل PostgreSQL.
حين يتجاوز جدول مكاني بضعة آلاف من الصفوف، ستحتاج إلى بناء فهرس لتسريع عمليات البحث المكاني في البيانات. فهارس GiST عالية الأداء ما دام حجمها لا يتجاوز مقدار ذاكرة RAM المتاحة لقاعدة البيانات، وما دمت قادرًا على تحمّل حجم تخزين الفهرس وتكلفة تحديثه عند الكتابة. وإلا، يمكن النظر في فهرس BRIN كبديل للجداول الكبيرة جدًا.
يخزّن فهرس BRIN المستطيل المحيط بجميع الأشكال الهندسية الموجودة في الصفوف ضمن مجموعة متجاورة من كتل الجدول، تُسمى نطاق الكتل. عند تنفيذ استعلام باستخدام الفهرس، تُمسح نطاقات الكتل للعثور على تلك التي تتقاطع مع امتداد الاستعلام. ولا يكون ذلك فعالًا إلا إذا كانت البيانات مرتبة فعليًا بحيث يكون التداخل بين المستطيلات المحيطة بنطاقات الكتل أقل ما يمكن (ويُفضّل أن تكون متنافية). يكون الفهرس الناتج صغير الحجم جدًا، لكنه عادةً أقل أداءً في القراءة من فهرس GiST على البيانات نفسها.
بناء فهرس BRIN أقل استهلاكًا للمعالج بكثير من بناء فهرس GiST. ومن الشائع أن يكون بناء فهرس BRIN أسرع بعشر مرات من بناء فهرس GiST على البيانات نفسها. ولأن فهرس BRIN يخزّن مستطيلًا محيطًا واحدًا فقط لكل نطاق من كتل الجدول، فمن الشائع أن يستهلك مساحة قرص أقل بما يصل إلى ألف مرة من فهرس GiST.
يمكنك اختيار عدد الكتل التي تُلخَّص في النطاق الواحد. إذا قلّلت هذا العدد، فسيكون الفهرس أكبر لكنه سيوفر على الأرجح أداءً أفضل.
لكي يكون BRIN فعالًا، ينبغي تخزين بيانات الجدول بترتيب فعلي يقلل من مقدار التداخل بين امتدادات الكتل. قد تكون البيانات مرتبة ترتيبًا مناسبًا مسبقًا (على سبيل المثال، إذا حُمّلت من مجموعة بيانات أخرى مرتبة مكانيًا). وإلا، يمكن تحقيق ذلك بترتيب البيانات وفق مفتاح مكاني أحادي البعد. إحدى طرق ذلك إنشاء جدول جديد مرتب حسب قيم geometry (التي تستخدم في إصدارات PostGIS الحديثة ترتيبًا فعالًا وفق منحنى هيلبرت):
CREATE TABLE table_sorted AS SELECT * FROM table ORDER BY geom;
بدلًا من ذلك، يمكن ترتيب البيانات في مكانها باستخدام GeoHash كفهرس (مؤقت)، ثم إجراء التجميع (clustering) على ذلك الفهرس:
CREATE INDEX idx_temp_geohash ON table
USING btree (ST_GeoHash( ST_Transform( geom, 4326 ), 20));
CLUSTER table USING idx_temp_geohash;
صيغة بناء فهرس BRIN على عمود geometry هي:
CREATE INDEX [indexname] ON [tablename] USING BRIN ( [geome_col] );
تبني الصيغة أعلاه فهرسًا ثنائي الأبعاد. لبناء فهرس ثلاثي الأبعاد، استخدم هذه الصيغة:
CREATE INDEX [indexname] ON [tablename]
USING BRIN ([geome_col] brin_geometry_inclusion_ops_3d);
يمكنك أيضًا الحصول على فهرس رباعي الأبعاد باستخدام فئة العوامل 4D:
CREATE INDEX [indexname] ON [tablename]
USING BRIN ([geome_col] brin_geometry_inclusion_ops_4d);
تستخدم الأوامر أعلاه العدد الافتراضي للكتل في النطاق، وهو 128. لتحديد عدد الكتل التي تُلخَّص في النطاق، استخدم هذه الصيغة
CREATE INDEX [indexname] ON [tablename]
USING BRIN ( [geome_col] ) WITH (pages_per_range = [number]);
تذكّر أن فهرس BRIN يخزّن مُدخلًا واحدًا فقط في الفهرس لعدد كبير من الصفوف. إذا كان جدولك يخزّن أشكالًا هندسية بأعداد أبعاد مختلطة، فمن المرجح أن يكون أداء الفهرس الناتج ضعيفًا. يمكنك تجنّب هذا التراجع في الأداء باختيار فئة العوامل ذات أقل عدد من الأبعاد بين الأشكال الهندسية المخزّنة
نوع البيانات geography مدعوم في فهرسة BRIN. صيغة بناء فهرس BRIN على عمود geography هي:
CREATE INDEX [indexname] ON [tablename] USING BRIN ( [geog_col] );
تبني الصيغة أعلاه فهرسًا ثنائي الأبعاد للكائنات الجغرافية المكانية على الشكل الإهليلجي (spheroid).
حاليًا، لا يتوفر سوى "دعم الاحتواء"، أي أنه لا يمكن استخدام سوى العوامل && و~ و@ في الحالات ثنائية الأبعاد (لكل من geometry وgeography)، والعامل &&& فقط للأشكال الهندسية ثلاثية الأبعاد. ولا يوجد حاليًا دعم لعمليات بحث kNN.
من الفروق المهمة بين BRIN وأنواع الفهارس الأخرى أن قاعدة البيانات لا تصون الفهرس ديناميكيًا. إذ تُلحق التغييرات على البيانات المكانية في الجدول بنهاية الفهرس فحسب. وسيؤدي ذلك إلى تراجع أداء البحث في الفهرس بمرور الوقت. يمكن تحديث الفهرس بتنفيذ VACUUM، أو باستخدام دالة خاصة هي brin_summarize_new_values(regclass). لهذا السبب قد يكون BRIN أنسب للاستخدام مع البيانات المخصصة للقراءة فقط أو التي نادرًا ما تتغير. لمزيد من المعلومات راجع الدليل.
خلاصة استخدام BRIN للبيانات المكانية:
-
وقت بناء الفهرس سريع جدًا، وحجم الفهرس صغير جدًا.
-
وقت الاستعلام بالفهرس أبطأ من GiST، لكنه قد يظل مقبولًا جدًا.
-
يتطلب أن تكون بيانات الجدول مرتبة ترتيبًا مكانيًا.
-
يتطلب صيانة يدوية للفهرس.
-
الأنسب للجداول الكبيرة جدًا ذات التداخل المنخفض أو المنعدم (مثل النقاط)، والثابتة أو التي نادرًا ما تتغير.
-
أكثر فعالية للاستعلامات التي تُعيد أعدادًا كبيرة نسبيًا من السجلات.
4.9.3. فهارس SP-GiST
SP-GiST اختصار لـ "Space-Partitioned Generalized Search Tree" (شجرة البحث المعمّمة المقسّمة مكانيًا)، وهي شكل عام من الفهرسة لأنواع البيانات متعددة الأبعاد يدعم أشجار البحث المقسّمة، مثل أشجار quad-tree وأشجار k-d وأشجار radix (tries). والسمة المشتركة لهذه البنى أنها تقسّم فضاء البحث مرارًا إلى أقسام لا يلزم أن تكون متساوية الحجم. وإضافة إلى الفهرسة المكانية، تُستخدم SP-GiST لتسريع البحث في أنواع كثيرة من البيانات، مثل توجيه الهاتف، وتوجيه IP، والبحث عن السلاسل الجزئية، وغيرها. لمزيد من المعلومات انظر دليل PostgreSQL.
كما هو الحال مع فهارس GiST، فإن فهارس SP-GiST فاقدة (lossy)، بمعنى أنها تخزّن المستطيل المحيط بالكائنات المكانية. ويمكن اعتبار فهارس SP-GiST بديلًا لفهارس GiST.
حين يتجاوز جدول بيانات GIS بضعة آلاف من الصفوف، يمكن استخدام فهرس SP-GiST لتسريع عمليات البحث المكاني في البيانات. صيغة بناء فهرس SP-GiST على عمود "geometry" هي كالآتي:
CREATE INDEX [indexname] ON [tablename] USING SPGIST ( [geometryfield] );
ستبني الصيغة أعلاه فهرسًا ثنائي الأبعاد. ويمكن إنشاء فهرس ثلاثي الأبعاد للنوع geometry باستخدام فئة العوامل 3D:
CREATE INDEX [indexname] ON [tablename] USING SPGIST ([geometryfield] spgist_geometry_ops_3d);
بناء فهرس مكاني عملية كثيفة الحساب. كما أنها تمنع الكتابة في جدولك طوال مدة الإنشاء، لذا قد ترغب في نظام الإنتاج في تنفيذها بطريقة أبطأ تراعي CONCURRENTLY:
CREATE INDEX CONCURRENTLY [indexname] ON [tablename] USING SPGIST ( [geometryfield] );
بعد بناء فهرس، يكون من المفيد أحيانًا إجبار PostgreSQL على جمع إحصاءات الجدول، التي تُستخدم لتحسين خطط الاستعلام:
VACUUM ANALYZE [table_name] [(column_name)];
يمكن لفهرس SP-GiST تسريع الاستعلامات التي تتضمن العوامل الآتية:
-
<< و&< و&> و>> و<<| و&<| و|&> و|>> و&& و@> و<@ و~=، للفهارس ثنائية الأبعاد،
-
&/& و~== و@>> و<<@، للفهارس ثلاثية الأبعاد.
لا يوجد دعم لعمليات بحث kNN في الوقت الحالي.
4.9.4. ضبط استخدام الفهارس
عادةً ما تُسرّع الفهارس الوصول إلى البيانات بشكل غير مرئي: فبمجرد بناء الفهرس، يقرر مخطِّط الاستعلامات في PostgreSQL تلقائيًا متى يستخدمه لتحسين أداء الاستعلام. لكن توجد حالات لا يختار فيها المخطِّط استخدام الفهارس الموجودة، فتنتهي الاستعلامات إلى استخدام مسح تسلسلي بطيء بدلًا من الفهرس المكاني.
إذا وجدت أن فهارسك المكانية لا تُستخدم، فهناك بعض الأمور التي يمكنك فعلها:
-
افحص خطة الاستعلام وتحقق من أن استعلامك يحسب فعلًا ما تحتاجه. فقد يؤدي JOIN خاطئ، سواء كان منسيًا أو إلى جدول خاطئ، إلى استرجاع سجلات الجدول عدة مرات على نحو غير متوقع. للحصول على خطة الاستعلام، نفّذه مع وضع
EXPLAINقبله. -
تأكد من جمع الإحصاءات حول عدد القيم وتوزيعها في الجدول، لتزويد مخطِّط الاستعلامات بمعلومات أفضل لاتخاذ القرارات بشأن استخدام الفهارس. يحسب الأمر VACUUM ANALYZE كليهما.
ينبغي على أي حال تنظيف (vacuum) قواعد بياناتك بانتظام. ويشغّل كثير من مديري قواعد بيانات PostgreSQL الأمر VACUUM كمهمة cron منتظمة خارج أوقات الذروة.
-
إذا لم يُفد التنظيف، يمكنك إجبار المخطِّط مؤقتًا على استخدام معلومات الفهرس باستخدام الأمر SET ENABLE_SEQSCAN TO OFF;. بهذه الطريقة يمكنك التحقق مما إذا كان المخطِّط قادرًا أصلًا على توليد خطة استعلام مُسرَّعة بالفهرس لاستعلامك. ينبغي ألا تستخدم هذا الأمر إلا لتصحيح الأخطاء؛ فعمومًا، يعرف المخطِّط أفضل منك متى تُستخدم الفهارس. وبعد تشغيل استعلامك، لا تنسَ تشغيل SET ENABLE_SEQSCAN TO ON; حتى يعمل المخطِّط بشكل طبيعي مع الاستعلامات الأخرى.
-
إذا ساعد SET ENABLE_SEQSCAN TO OFF; على تسريع تشغيل استعلامك، فمن المرجح أن Postgres غير مضبوط لعتادك. إذا وجدت أن المخطِّط مخطئ في تقدير تكلفة المسح التسلسلي مقابل المسح بالفهرس، فجرّب تقليل قيمة
RANDOM_PAGE_COSTفيpostgresql.conf، أو استخدم SET RANDOM_PAGE_COST TO 1.1;. القيمة الافتراضية لـRANDOM_PAGE_COSTهي 4.0. جرّب ضبطها على 1.1 (لأقراص SSD) أو 2.0 (للأقراص المغناطيسية السريعة). يؤدي تقليل القيمة إلى زيادة احتمال استخدام المخطِّط للمسح بالفهرس. -
إذا لم يُفد SET ENABLE_SEQSCAN TO OFF; استعلامك، فقد يكون الاستعلام يستخدم بنية SQL لا يستطيع مخطِّط Postgres تحسينها بعد. وقد يكون من الممكن إعادة كتابة الاستعلام بطريقة يستطيع المخطِّط التعامل معها. على سبيل المثال، قد لا يُنتج استعلام فرعي يتضمن SELECT ضمنيًا خطة فعالة، لكن يمكن ربما إعادة كتابته باستخدام LATERAL JOIN.
لمزيد من المعلومات انظر قسم دليل Postgres الخاص بـ تخطيط الاستعلامات.