AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 280533
Accepted
DevelJoe
DevelJoe
Asked: 2020-11-30 07:10:22 +0800 CST2020-11-30 07:10:22 +0800 CST 2020-11-30 07:10:22 +0800 CST

Consultar dados via nome de usuário - par - melhor desempenho

  • 772

RDBMS: MariaDB 10.3

Digamos que você tenha uma tabela que armazena informações específicas ( info_1, info_2, etc.) de acordo com um determinado par de nomes de usuário; igual a:

+----------+----------+----------+----------+----------+------+--..
|  user_1  |  user_2  |  info_1  |  info_2  |  info_3  |  ..  |  ..
+----------+----------+----------+----------+----------+------+--..

onde os valores de user_1e user_2cada igual a um nome de usuário específico e distinto ( VARCHAR(50)), e são definidos como índice de várias colunas (user_1,user_2) da tabela na criação. As consultas que meu aplicativo faz pesquisa em função de:

A) um determinado par de usuários:

WHERE user_1 = name_1 AND user_2 = name_2 OR user_1 = name_2 AND user_2 = name_1

B) um determinado usuário/retorno todos os registros onde um determinado usuário é um dos membros:

WHERE user_1 = name_1 OR user_1 = '%' AND user_2 = name_1

Problema: Devo garantir que as pesquisas sejam sempre indexadas. Ao usar uma ORcláusula, uma varredura completa da tabela é executada a cada vez.

SOLUÇÃO I)

Graças a esta resposta, as possíveis consultas que resultam em pesquisas indexadas para esses casos são:

A)

SELECT * FROM my_table WHERE user_1 = name_1 AND user_2 = name_2
UNION ALL
SELECT * FROM my_table WHERE user_1 = name_2 AND user_2 = name_1;

B)

SELECT * FROM my_table WHERE user_1 = name_1
UNION ALL
SELECT * FROM my_table WHERE user_1 = '%' AND user_2 = name_1;

Porém com a desvantagem de sempre usar duas SELECTinstruções e uma WHEREcláusula que sempre será em vão (pois sempre haverá um registro por par de usuário). É por isso que tentei otimizar ainda mais a consulta usando um índice de texto completo , o que resultou na seguinte tabela:

SOLUÇÃO II)

+---------+----------+----------+----------+------+--..
|  users  |  info_1  |  info_2  |  info_3  |  ..  |  ..
+---------+----------+----------+----------+------+--..

onde usersfoi definido como FULLTEXT VARCHAR(150), e seu valor sempre corresponde ao formato name_1-name_2, enquanto eu usei um hífen porque uma vírgula é usada na MATCH...AGAINSTsintaxe para executar consultas de índice de texto completo.

Com essa estrutura, agora obtenho as seguintes novas possibilidades de consulta para A) e B):

A)

SELECT * FROM my_table WHERE MATCH(users) AGAINST ('"name_1-name_2","name_2-name_1"');

B)

SELECT * FROM my_table WHERE MATCH(users) AGAINST ('name_1');

O que na minha opinião facilita drasticamente a estrutura da consulta, e não usa nem duas SELECTdeclarações, nem uma WHEREcláusula adicional que será em vão. Ainda assim, como ainda não sei muito sobre otimização de desempenho de consulta e a comparação de pesquisas de índice de texto completo com pesquisas de índice regulares, gostaria de saber qual solução de I e II pode ter melhor desempenho e por quê? Ou existe ainda uma abordagem melhor?

optimization query-performance
  • 1 1 respostas
  • 74 Views

1 respostas

  • Voted
  1. Best Answer
    Rick James
    2020-11-30T16:29:03+08:002020-11-30T16:29:03+08:00

    Crítica

    1A não pode usar índices por causa deOR

    1B -- user_1 = '%'impede o uso de INDEX(user_1, ...), então a solução 1B está fora.

    1B pode ser recuperado tendo um segundo índice: INDEX(user_2). Então basta dizer

    SELECT * FROM my_table WHERE user_1 = name_1
    UNION ALL
    SELECT * FROM my_table WHERE user_2 = name_1;
    

    2-- FULLTEXT tem limitações, como o tamanho da "palavra". Portanto, seja cauteloso.

    2A ( WHERE MATCH(users) AGAINST ('"name_1-name_2","name_2-name_1"')-- provavelmente é suficiente dizer simplesmente WHERE MATCH(users) AGAINST ('+name_1 +name_2' IN BOOLEAN MODE); The +` diz que ambos são necessários, mas em qualquer ordem.

    2B -- OK (com as ressalvas acima)

    FULLTEXT, quando aplicável , provavelmente terá um bom desempenho. Aqui estão dois truques que usei:

    WHERE MATCH(text) AGAINST("R +James" IN BOOLEAN MODE)
    

    A 'palavra' curta (R) será ignorada; ele irá procurar por James eficientemente. Observe o uso seletivo de '+'.

    WHERE MATCH(text) AGAINST("R +Anders" IN BOOLEAN MODE)
      AND user LIKE "%R. Anders%"
    

    Isso pressupõe que o nome pode estar no meio de uma coluna grande e eu preciso verificar a inicial. O teste FT será o primeiro (e rápido), seguido pelo LIKE (lento, mas contra poucas linhas).

    Isso ainda tem problemas porque "E. Anders e R. Anderson" seriam pegos erroneamente.

    (Etc, etc. Mas eu discordo do seu caso de uso simples de 2 palavras.)

    Linha inferior:

    1B (índice extra) é o ideal. (Mas suspeito que você tenha diluído a Pergunta.)

    FULLTEXTseria minha próxima escolha.

    Deixe-me adicionar uma opção 3:

    Classifique os usuários antes de inserir e ao consultar. Aquilo é

    INSERT ... (user1, user2)
       VALUES
       (LEAST(?, ?), GREATEST(?, ?))
    

    então você precisa (para o caso A) apenas INDEX(user1, user2)junto com

    WHERE user1 = LEAST(?, ?)
      AND user1 = GREATEST(?, ?)
    

    Infelizmente, isso provavelmente atrapalhará o caso B. ( Todas as linhas têm 2 nomes de usuário, mas algumas consultas têm apenas 1 usuário?)

    E Opção 4

    Tenha outra tabela que mapeie os nomes de usuário my_tablepor id. Normalmente 2 linhas nesta nova tabela para cada linha em my_table. Opcionalmente, jogue as colunas do usuário de my_table.

    Não entrarei no resto dos detalhes; eles ficam confusos.

    • 0

relate perguntas

  • Como o Yelp calcula com eficiência a distância no banco de dados?

  • Otimização de consultas

  • Como devo otimizar o armazenamento para esta tabela?

  • DBMS_REDEFINITION vs EXCHANGE PARTITION no oracle

  • Existe uma boa "regra de ouro" para traduzir o custo EXPLAIN para o tempo de execução (relógio de parede)?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve