Jaka jest różnica między POINT (X, Y) i GeomFromText („POINT (XY)”)?

17

Chciałbym przechowywać pewne geometryczne pozycje w mojej bazie danych MySQL. W tym celu używam typu danych POINT. Niemal wszędzie czytam, że GeomFromTextnależy użyć tej funkcji do wstawienia danych do tabeli.

Jednak dowiedziałem się, że to POINT(X,Y)również działa. Nie znalazłem żadnego opisu, dlaczego GeomFromTextnależy go użyć zamiast POINT.

Na przykład mam następującą prostą relację:

CREATE TABLE Site (
    SiteID      BIGINT UNSIGNED,
    Position    POINT
);

I mogę wstawić wartości, używając następujących dwóch wariantów:

INSERT INTO Site (
    1,
    GeomFromText( 'POINT(48.19976 16.45572)' )
);

INSERT INTO Site (
    2,
    POINT(48.19976, 16.45572)
);

Kiedy przeglądam tabelę ( SELECT * FROM Site), widzę ten sam binarny obiekt blob dla lokalizacji, a kiedy przeglądam współrzędne ( SELECT *, AsText(Position) FROM Site), widzę te same wartości.

Dlaczego więc należy używać GeomFromText? Czy istnieją (znane) różnice w wydajności między tymi dwoma wariantami? Jak to rozwiązać w innych systemach baz danych niż MySQL?

ComSubVie
źródło
Nie wiem, czy są jakieś różnice w wydajności (nie sądzę, ale to tylko przypuszczenie). Ale drugie podejście byłoby prostsze przy konwersji wartości szerokości i długości geograficznej z innej tabeli. INSERT INTO Site (Position) SELECT POINT(latitude, longitude) FROM tmpjest prostsze niż...SELECT GeomFromText(CONCAT('POINT(',latitude,' ',longitude,')' )) ...
ypercubeᵀᴹ
Uważam też, że drugi wariant jest znacznie prostszy w budowie, dlatego zastanawiam się, czy zwykle pierwszy z nich jest używany prawie wszędzie, gdzie widziałem używane rozszerzenia przestrzenne MySQL.
ComSubVie,
Właśnie próbowałem wstawić 10.000.000 lokalizacji w powyższej tabeli (na moim hoście) przy użyciu obu wariantów i nie wykryłem żadnej mierzalnej różnicy wydajności.
ComSubVie,
Proszę rozważyć ponowną ocenę tego w świetle MySQL 8+ i dla potomności: dba.stackexchange.com/a/227049/2639
Evan Carroll

Odpowiedzi:

16

Istnieją dwa różne formaty binarne związane z rozszerzeniami przestrzennymi MySQL, „dobrze znany format binarny” (WKB) ze standardów oraz wewnętrzny GEOMETRYtyp danych MySQL .

Przed MySQL 5.1.35 funkcje takie POINT()jak nie zwracały wewnętrznego typu danych MySQL; zwrócili WKB ... więc wcześniej trzeba było to zrobić:

INSERT INTO t1 (pt_col) VALUES (GeomFromWKB(Point(1,2)));

Ale teraz, jak w twoim przykładzie, działa to:

INSERT INTO t1 (pt_col) VALUES(Point(1,2));

Na uznanie twórców, kiedy zmienili Point()funkcje podobne do (bardziej zdrowo) zwracanych GEOMETRYobiektów, zezwolili GeomFromWKB()i podobne funkcje faktycznie akceptują dane WKB lub MySQL Geometry jako dane wejściowe, nawet jeśli funkcje mają przyjmować WKB jako dane wejściowe.

Fakt, że pierwsza metoda działa (mimo że jest niepoprawna technicznie) na nowszych serwerach, a druga metoda wcale nie działa przed MySQL 5.1.35, może wyjaśniać, dlaczego przykłady zostały napisane przy użyciu podejścia, które widziałeś - całkowicie unikaj problemu. W przeciwnym razie ... Nie mam tu nic.

Łączenie, a następnie parsowanie tekstu wydaje się intuicyjnie wolniejsze i bardziej podatne na błędy niż funkcje, które akceptują odpowiednie zmienne jako dane wejściowe, więc nie mogę wymyślić żadnego powodu, aby tworzyć połączone łańcuchy i używać funkcji tekstowych.

http://dev.mysql.com/doc/refman/5.1/en/creating-spatial-values.html#gis-wkb-functions

http://dev.mysql.com/doc/relnotes/mysql/5.1/en/news-5-1-35.html

Michael - sqlbot
źródło
1
Dzięki, interesujące, że jest to wspomniane jedynie jako „przypis” w uwagach do wydania i nigdzie w dokumentacji. Więc będę trzymać się z dala od metod tekstowych.
ComSubVie
1
Dlaczego 5 lat później dokumentacja MySQL wciąż podaje przykłady użycia funkcji ST_GeomFromText () podczas wstawiania? Czy ta odpowiedź jest nadal aktualna? To trochę mylące .. dev.mysql.com/doc/refman/5.7/en/popicing-spatial-columns.html
Matt Kieran
1
@MattKieran WKB i WKT to znormalizowane, otwarte formaty do wyrażania danych geoprzestrzennych. Przykłady wykorzystują je, ponieważ zorientowane na standardy aplikacje geoprzestrzenne mogą już przechowywać dane w tych formatach, umożliwiając MySQL akceptowanie zewnętrznych geometrii jako jednego argumentu ST_GeomFromText()i podobnych funkcji konwersji, zamiast wymagać od zewnętrznych aplikacji używania natywnych funkcji SQL konstruujących obiekty geometryczne, które znajdują się w Spatial Function Reference . Dokumenty można lepiej zorganizować.
Michael - sqlbot
Również @MattKieran ta odpowiedź jest nadal aktualna tylko w tym sensie, że wyjaśnia, dlaczego starsze przykłady mogą być pisane wbrew temu, co wskazują dokumenty, niezależnie od tego, dlaczego MySQL działa z niedopasowaniem typu pozornego, które wydaje się wskazywać na używanie funkcji w ten sposób. Wszystkie trzy metody - natywne funkcje SQL, WKB (binarny) lub WKT (tekst) - są poprawne. Nie trzeba już konwertować wartości zwracanych przez funkcję natywną z WKB, ponieważ ich typy zwracane nie są już WKB, jak wiele lat temu.
Michael - sqlbot
4

MySQL 8+

Dla potomności liczy się tylko to

  • Point(X,Y)jest konstruktorem liczb z precyzją i nie wymaga wcześniejszej konwersji na tekst, dzięki czemu jest szybszy. Gwarantowane jest również ZWROT POINTLUB USZKODZENIE . To sprawia, że ​​jest mocno wpisany, jeśli chcesz o tym myśleć.
  • Konstruktory dobrze znanego tekstu (WKT) : są one zawsze wolniejsze, ponieważ wymagają dodatkowego kroku, aby przeanalizować dobrze znany tekst (WKT) . Uwaga: w starszych wersjach można je było znaleźć bez ST_prefiksu; jeśli jest dostępny, użyj wersji z ST_prefiksem. Konstruktorów WKT należy używać tylko wtedy, gdy wprowadzony tekst jest już dobrze znany. Jeśli nie, użyj Point(x,y)powyższego konstruktora.
    • ST_GeomFromText(wkt, srid)może zwrócić KAŻDY typ przestrzenny obsługiwany przez MySQL i reprezentowany przez WKT. To sprawia, że ​​jest luźno wpisany, jeśli chcesz o tym myśleć.
    • ST_PointFromText(wkt, srid)mocno napisany POINTkonstruktor z dobrze znanego tekstu.

Przejrzystość

Pomijając lekcję historii, NIGDY nie rób GeomFromText(Point(x,y)). To okropne, nieobsługiwane i nieudokumentowane.

Evan Carroll
źródło
-1

Za pomocą GeomFromText lub dowolnej innej funkcji * FromText możesz określić SRID . Nie sądzę, że możesz to zrobić inaczej.

PointFromText('POINT(lat lng)', 4326)
fromvega
źródło
To powinno być na odwrót, tj. POINT(lng lat)ZamiastPOINT(lat lng)
Zishan
MySQL i tak nie używa SRID. To jest całkiem bezużyteczne. Jeśli potrzebujesz identyfikatorów SRID, dokonaj migracji do PostgreSQL / PostGIS.
Evan Carroll,
1
MySQL 8 używa identyfikatorów SRID. W rzeczywistości mam problem z bazą danych MySQL migrowaną z 5.7 do 8 właśnie z powodu SRID.
cmoran92