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 / 68256
Accepted
Martin Smith
Martin Smith
Asked: 2014-06-15 15:27:34 +0800 CST2014-06-15 15:27:34 +0800 CST 2014-06-15 15:27:34 +0800 CST

Busca de intervalo de retorno no índice composto anulável?

  • 772

Para o seguinte esquema e dados de exemplo

CREATE TABLE T
  (
     A INT NULL,
     B INT NOT NULL IDENTITY,
     C CHAR(8000) NULL,
     UNIQUE CLUSTERED (A, B)
  )

INSERT INTO T
            (A)
SELECT NULLIF(( ( ROW_NUMBER() OVER (ORDER BY @@SPID) - 1 ) / 1003 ), 0)
FROM   master..spt_values 

Um aplicativo está processando as linhas desta tabela na ordem do índice clusterizado em blocos de 1.000 linhas.

As primeiras 1.000 linhas são recuperadas da consulta a seguir.

SELECT TOP 1000 *
FROM   T
ORDER  BY A, B 

A linha final desse conjunto está abaixo

+------+------+
|  A   |  B   |
+------+------+
| NULL | 1000 |
+------+------+

Existe alguma maneira de escrever uma consulta que apenas busque essa chave de índice composto e a siga para recuperar o próximo bloco de 1.000 linhas?

/*Pseudo Syntax*/
SELECT TOP 1000 *
FROM   T
WHERE (A, B) is_ordered_after (@A, @B)
ORDER  BY A, B 

O menor número de leituras que consegui até agora é 1020, mas a consulta parece muito complicada. Existe uma maneira mais simples de eficiência igual ou melhor? Talvez aquele que consegue fazer tudo em uma busca de alcance?

DECLARE @A INT = NULL, @B INT = 1000

;WITH UnProcessed
     AS (SELECT *
         FROM   T
         WHERE  ( EXISTS(SELECT A
                         INTERSECT
                         SELECT @A)
                  AND B > @B )
         UNION ALL
         SELECT *
         FROM   T
         WHERE @A IS NULL AND A IS NOT NULL
         UNION ALL
         SELECT *
         FROM   T
         WHERE A > @A        
         )
SELECT TOP 1000 *
FROM   UnProcessed
ORDER  BY A,
          B 

insira a descrição da imagem aqui


FWIW: Se a coluna Afor feita NOT NULLe um valor sentinela -1for usado, o plano de execução equivalente certamente parecerá mais simples

insira a descrição da imagem aqui

Mas o único operador de busca no plano ainda realiza duas buscas em vez de reduzi-lo em um único intervalo contíguo e as leituras lógicas são praticamente as mesmas, então estou suspeitando que talvez isso seja tão bom quanto será.

sql-server index
  • 1 1 respostas
  • 2041 Views

1 respostas

  • Voted
  1. Best Answer
    Paul White
    2014-06-16T17:03:43+08:002014-06-16T17:03:43+08:00

    Existe alguma maneira de escrever uma consulta que apenas busque essa chave de índice composto e a siga para recuperar o próximo bloco de 1.000 linhas?

    Uma solução favorita minha é usar um APIcursor:

    SET NOCOUNT ON;
    SET STATISTICS IO ON;
    
    DECLARE 
        @cur integer,
        -- FAST_FORWARD, AUTO_FETCH, AUTO_CLOSE, CHECK_ACCEPTED_TYPES, FAST_FORWARD_ACCEPTABLE
        @scrollopt integer = 16 | 8192 | 16384 | 32768 | 1048576,
        -- READ_ONLY, CHECK_ACCEPTED_OPTS, READ_ONLY_ACCEPTABLE
        @ccopt integer = 1 | 32768 | 65536, 
        @rowcount integer = 1000,
        @rc integer;
    
    -- Open the cursor and return (up to) the first 1000 rows
    EXECUTE @rc = sys.sp_cursoropen
        @cur OUTPUT,
        N'
        SELECT A, B, C
        FROM T
        ORDER BY A, B;
        ',
        @scrollopt OUTPUT,
        @ccopt OUTPUT,
        @rowcount OUTPUT;
    
    IF @rc <> 16 -- FastForward cursor automatically closed
    BEGIN
        -- Name the cursor so we can use CURSOR_STATUS
        EXECUTE sys.sp_cursoroption
            @cur, 
            2, 
            'MyCursorName';
    
        -- Until the cursor auto-closes
        WHILE CURSOR_STATUS('global', 'MyCursorName') = 1
        BEGIN
            EXECUTE sys.sp_cursorfetch
                @cur,
                2,
                0,
                1000;
        END;
    END;
    
    SET STATISTICS IO OFF;
    

    A estratégia geral é uma varredura única que lembra sua posição entre as chamadas. Usar um APIcursor significa que podemos retornar um bloco de linhas em vez de uma por vez, como seria o caso de um T-SQLcursor:

    Planos de execução

    A STATISTICS IOsaída é:

    Table 'T'. Scan count 1, logical reads 1011, physical reads 0, read-ahead reads 0
    Table 'T'. Scan count 1, logical reads 1001, physical reads 0, read-ahead reads 0
    Table 'T'. Scan count 1, logical reads 516, physical reads 0, read-ahead reads 0
    
    • 21

relate perguntas

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Quanto "Padding" coloco em meus índices?

  • Como determinar se um Índice é necessário ou necessário

  • O que significa "índice" em RDBMSs? [fechado]

  • Como criar um índice condicional no MySQL?

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