Qual é a diferença entre POINT (X, Y) e GeomFromText ("POINT (XY)")?

17

Eu gostaria de armazenar algumas posições geométricas no meu banco de dados MySQL. Para isso, eu uso o tipo de dados POINT. Em quase todos os lugares, li que a função GeomFromTextdeve ser usada para inserir dados na tabela.

No entanto, descobri que POINT(X,Y)também funciona. Não encontrei nenhuma descrição do porquê GeomFromTextusar em vez de POINT.

Por exemplo, tenho a seguinte relação simples:

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

E posso inserir valores usando as duas seguintes variantes:

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

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

Quando visualizo a tabela ( SELECT * FROM Site), vejo o mesmo blob binário do local e, quando visualizo as coordenadas ( SELECT *, AsText(Position) FROM Site), também vejo os mesmos valores.

Então, por que o GeomFromText deve ser usado? Existem diferenças de desempenho (conhecidas) entre essas duas variantes? Como isso é resolvido em outros sistemas de banco de dados que não o MySQL?

ComSubVie
fonte
Não sei se existem diferenças de desempenho (acho que não, mas isso é apenas um palpite). Mas a segunda abordagem seria mais simples ao converter valores de latitude e longitude de outra tabela. INSERT INTO Site (Position) SELECT POINT(latitude, longitude) FROM tmpÉ mais simples que...SELECT GeomFromText(CONCAT('POINT(',latitude,' ',longitude,')' )) ...
ypercubeᵀᴹ
Eu também considero a segunda variante muito mais simples de construir, é por isso que me pergunto que geralmente a primeira é usada em quase todos os lugares onde vi extensões espaciais do MySQL usadas.
precisa saber é o seguinte
Eu apenas tentei inserir 10.000.000 locais na tabela acima (no meu host) usando as duas variantes e não detectou nenhuma diferença mensurável de desempenho.
ComSubVie
Por favor, considere reavaliar isso à luz do MySQL 8+ e para posteridade: dba.stackexchange.com/a/227049/2639
Evan Carroll

Respostas:

16

Existem dois formatos binários diferentes relacionados às extensões espaciais do MySQL, o formato "bem conhecido binário" (WKB) dos padrões e o GEOMETRYtipo de dados interno do MySQL .

Antes do MySQL 5.1.35, funções como POINT()não retornavam o tipo de dados interno do MySQL; eles retornaram o WKB ... então antes disso, você tinha que fazer o seguinte:

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

Mas agora, como no seu exemplo, isso funciona:

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

Para crédito dos desenvolvedores, quando eles mudaram Point()e funções semelhantes para retornar GEOMETRYobjetos (com mais prudência) , eles permitiram que GeomFromWKB()funções semelhantes aceitassem realmente dados WKB ou MySQL Geometry como entrada, mesmo que as funções pretendam aceitar WKB como entrada.

O fato de o 1º método funcionar (apesar de tecnicamente errado) em servidores mais recentes e o 2º método não funcionar antes do MySQL 5.1.35 pode explicar por que os exemplos foram escritos usando a abordagem que você já viu - para evite o problema completamente. Caso contrário ... não tenho nada aqui.

Concatenar e depois analisar o texto parece intuitivamente mais lento e propenso a erros do que as funções que aceitam variáveis ​​apropriadas como entrada; portanto, não consigo pensar em nenhum motivo para criar seqüências de caracteres concatenadas e usar as funções baseadas em texto.

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
fonte
1
Obrigado, interessante que isso seja mencionado apenas como uma "nota de rodapé" nas notas de versão e em nenhum lugar na documentação. Então, eu vou ficar longe dos métodos baseados em texto.
ComSubVie
1
Por que cinco anos depois os documentos do MySQL ainda dão exemplos de uso da função ST_GeomFromText () ao inserir? Essa resposta ainda é relevante? É um pouco de confundir .. dev.mysql.com/doc/refman/5.7/en/populating-spatial-columns.html
Matt Kieran
1
O @MattKieran WKB e o WKT são formatos abertos padronizados para expressar dados geoespaciais. Os exemplos os usam porque aplicativos geoespaciais orientados a padrões já podem conter dados nesses formatos, permitindo que o MySQL aceite geometrias externas como um argumento único ST_GeomFromText()e funções de conversão semelhantes, em vez de exigir que aplicativos externos usem as funções SQL nativas que constroem objetos de geometria, que são encontrados na referência de função espacial . Os documentos podem ser organizados melhor.
Michael - sqlbot
Além disso, @MattKieran esta resposta ainda é relevante no sentido em que explica por que exemplos mais antigos podem ser escritos ao contrário do que os documentos indicam, por que o MySQL trabalha com as aparentes incompatibilidades de tipo que o uso das funções dessa maneira parece indicar. Todos os três métodos - as funções SQL nativas, WKB (binário) ou WKT (texto) - são válidos. O que não é mais necessário é converter os valores de retorno da função nativa do WKB, porque seus tipos de retorno não são mais WKB como eram há muitos anos atrás.
Michael - sqlbot
4

MySQL 8+

Para a posteridade, a única coisa que importa é que

  • Point(X,Y)é um construtor de números com precisão e não requer conversão primeiro em texto, tornando-o mais rápido. Também é garantido RETORNAR POINTOU FALHAR . Isso o torna fortemente digitado, se você quiser pensar assim.
  • Construtores de texto conhecido (WKT) : esses são sempre mais lentos, pois exigem uma etapa adicional para analisar o texto conhecido (WKT) . Observe que em versões mais antigas, elas poderiam ser encontradas sem o ST_prefixo; Onde disponível, use a versão com o ST_prefixo. Use os construtores WKT apenas se sua entrada já for um texto conhecido. Caso contrário, use o Point(x,y)construtor acima.

Clareza

Ignorando a lição de história, NUNCA faça GeomFromText(Point(x,y)). Isso é horrível, sem suporte e sem documentos.

Evan Carroll
fonte
-1

Com o GeomFromText ou qualquer outra função * FromText, você pode especificar o SRID . Eu não acho que você possa fazê-lo de outra forma.

PointFromText('POINT(lat lng)', 4326)
fromvega
fonte
Esta deve ser a outra maneira, ou seja, em POINT(lng lat)vez dePOINT(lat lng)
Zishan
O MySQL não usa SRIDs de qualquer maneira. Então isso é bastante inútil. Se você precisar de SRIDs, migre para o PostgreSQL / PostGIS.
Evan Carroll
1
O MySQL 8 usa SRIDs. Na verdade, estou tendo problemas com um banco de dados MySQL migrado de 5,7 para 8 precisamente por causa dos SRIDs.
cmoran92 23/04