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 / 19803
Accepted
Haluk
Haluk
Asked: 2012-06-24 16:09:13 +0800 CST2012-06-24 16:09:13 +0800 CST 2012-06-24 16:09:13 +0800 CST

Alguma desvantagem de "SQL_BUFFER_RESULT" para MySQL SELECT?

  • 772

Eu tenho pesquisado o uso de SQL_BUFFER_RESULT. Principalmente, é referido como uma ajuda para reduzir os problemas de bloqueio de tabela.

Parece ser uma boa opção para usar.

No entanto, não consigo encontrar nenhuma desvantagem nisso. É uma opção que deve ser usada na maioria das vezes?

mysql select
  • 1 1 respostas
  • 5805 Views

1 respostas

  • Voted
  1. Best Answer
    Aaron Brown
    2012-06-25T13:31:28+08:002012-06-25T13:31:28+08:00

    SQL_BUFFER_RESULTcria uma tabela temporária no servidor para cada conjunto de resultados. Esta não é uma tabela temporária como CREATE TEMPORARY TABLE- é uma tabela temporária implícita, como seria criada ao usar uma cláusula GROUP BY ou com uma subconsulta. Como tal, todas as mesmas regras se aplicam .

    Primeiramente, vamos falar do problema que SQL_BUFFER_RESULTse pretende resolver:

    Quando o cliente solicita dados do servidor, até que todo o conjunto de resultados tenha sido transmitido ao cliente, a consulta ainda está "em execução" e alguns bloqueios ainda podem ser mantidos. Enquanto os dados estão sendo transmitidos, eles aparecerão no Sending dataestado. Depende da biblioteca se o cliente apenas obtém todos os dados de uma vez quando a consulta é executada ou se eles vão aparecendo conforme você seleciona as linhas, mas um exemplo de problema é o seguinte:

    resultset = conn["SELECT * FROM bigtable"]
    resultset.each do |row|
      data[:value] = row[:value]
      sleep 10 # do something expensive here
    end
    

    Obviamente artificial, mas no caso acima, se houver 1.000 linhas, a consulta ainda será executada ativamente por 10.000 segundos. Isso pode parecer muito improvável, mas muitos aplicativos têm "tempo de reflexão" entre a busca de cada linha porque eles fazem algum processamento. Isso é "uma coisa muito ruim de se fazer". Outro caso em que esse tipo de efeito de gotejamento pode ocorrer é com um grande conjunto de resultados em uma conexão lenta. Em última análise, o problema é o fluxo de dados para o cliente, fazendo com que a consulta permaneça em um estado ativo. SQL_BUFFER_RESULTresolve esse problema armazenando primeiro o resultado em uma tabela temporária, o que faz com que a consulta termine mais rapidamente, liberando todos os seus bloqueios (que bloqueios?). O conjunto de resultados é então alimentado ao cliente a partir da tabela temporária em vez da própria consulta.

    Isso parece ótimo!

    Mas...

    • As tabelas temporárias ocupam memória e outros recursos no servidor. Muitas tabelas temporárias == muitos recursos.
    • As tabelas que excedem o mínimo de tmp_table_size ou max_heap_table_size acabarão sendo convertidas em tabelas temporárias em disco, o que significa E/S adicional. Isso também significa que suas consultas demoram mais, pois assim que o tamanho da tabela MEMORY atinge tmp_table_size, ela é convertida em uma tabela MyISAM em disco.
    • Os campos BLOB/TEXT não podem ser armazenados como tabelas temporárias na memória (o mecanismo de armazenamento MEMORY não os suporta), portanto, sempre serão criados no disco.
    • criar tabelas temporárias é caro, especialmente quando elas estão em disco.
    • Considere que uma das primeiras coisas que tentamos otimizar ao olhar para um plano de explicação é "Usar temporário". SQL_BUFFER_RESULTliteralmente faz com que todas as consultas incluam "Usando temporário" (quase) o tempo todo. Meu pequeno teste mostrou que havia casos em que o MySQL não usava uma tabela temporária mesmo com essa dica, mas eles eram limitados (pesquisas de linha única na chave primária pareciam ser o único caso).

    Aqui estão alguns exemplos para mostrar o efeito:

    -- unindexed lookup w/out SQL_BUFFER_RESULT
    mysql> explain select  * from actor where first_name = 'THORA'\G
    *************************** 1. row ***************************
               id: 1
      select_type: SIMPLE
            table: actor
             type: ALL
    possible_keys: NULL
              key: NULL
          key_len: NULL
              ref: NULL
             rows: 203
            Extra: Using where
    1 row in set (0.00 sec)
    
    -- unindexed lookup w/SQL_BUFFER_RESULT
    mysql> explain select sql_buffer_result * from actor where first_name = 'THORA'\G
    *************************** 1. row ***************************
               id: 1
      select_type: SIMPLE
            table: actor
             type: ALL
    possible_keys: NULL
              key: NULL
          key_len: NULL
              ref: NULL
             rows: 203
            Extra: Using where; Using temporary
    1 row in set (0.00 sec)
    
    -- indexed lookup w/out SQL_BUFFER_RESULT
    mysql> explain select * from actor where last_name = 'TEMPLE'\G
    *************************** 1. row ***************************
               id: 1
      select_type: SIMPLE
            table: actor
             type: ref
    possible_keys: idx_actor_last_name
              key: idx_actor_last_name
          key_len: 137
              ref: const
             rows: 4
            Extra: Using where
    1 row in set (0.00 sec)
    
    
    -- indexed lookup w/SQL_BUFFER_RESULT
    mysql> explain select sql_buffer_result * from actor where last_name = 'TEMPLE'\G
    *************************** 1. row ***************************
               id: 1
      select_type: SIMPLE
            table: actor
             type: ref
    possible_keys: idx_actor_last_name
              key: idx_actor_last_name
          key_len: 137
              ref: const
             rows: 4
            Extra: Using where; Using temporary
    1 row in set (0.00 sec)
    
    
    -- primary key lookup w/SQL_BUFFER_RESULT
    mysql> explain select sql_buffer_result * from actor where actor_id = 200\G
    *************************** 1. row ***************************
               id: 1
      select_type: SIMPLE
            table: actor
             type: const
    possible_keys: PRIMARY
              key: PRIMARY
          key_len: 2
              ref: const
             rows: 1
            Extra: 
    1 row in set (0.00 sec)
    

    Para que serve o problema que está sendo resolvido? "fechaduras". Como esta é uma dica para consultas SELECT, a menos que você esteja usando FOR UPDATE ou LOCK IN SHARED MODE, há muito poucos bloqueios feitos em leituras de qualquer maneira e eles são muito rápidos, então você está resolvendo principalmente um problema que não existe. Exceções sempre existem, mas a sobrecarga de criar uma tabela temporária para quase todas as consultas superará em muito qualquer benefício obtido ao fazer com que os bloqueios desapareçam mais rapidamente.

    A recomendação do MySQL é usar a SQL_BUFFERED_RESULTdica ao recuperar um conjunto de resultados muito grande em uma conexão de rede para o cliente. Não consigo ver nenhum valor em usá-lo em outro contexto.

    Dito isso, você pode testar e definir isso "globalmente" definindo sql_buffer_result =1 no início de cada sessão. Em um ambiente com qualquer simultaneidade, eu prevejo resultados ruins.

    • 10

relate perguntas

  • Existem ferramentas de benchmarking do MySQL? [fechado]

  • Onde posso encontrar o log lento do mysql?

  • Como posso otimizar um mysqldump de um banco de dados grande?

  • Quando é o momento certo para usar o MariaDB em vez do MySQL e por quê?

  • Como um grupo pode rastrear alterações no esquema do banco de dados?

Sidebar

Stats

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

    Como ver a lista de bancos de dados no Oracle?

    • 8 respostas
  • Marko Smith

    Quão grande deve ser o mysql innodb_buffer_pool_size?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    restaurar a tabela do arquivo .frm e .ibd?

    • 10 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

    Como selecionar a primeira linha de cada grupo?

    • 6 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
    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
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +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
  • Martin Hope
    bernd_k Quando devo usar uma restrição exclusiva em vez de um índice exclusivo? 2011-01-05 02:32:27 +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