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 / 116780
Accepted
ijustlovemath
ijustlovemath
Asked: 2015-10-02 16:35:44 +0800 CST2015-10-02 16:35:44 +0800 CST 2015-10-02 16:35:44 +0800 CST

Como você armazenaria permutações de um conjunto de parâmetros de simulação, otimizando o armazenamento e a eficiência da análise?

  • 772

Vou executar várias simulações usando um aplicativo que escrevi em um futuro próximo e estou tendo problemas para projetar meu banco de dados com base nisso.

Veja como funciona. Cada simulação possui 6 parâmetros que podem variar, e cada parâmetro possui ~10 opções. Portanto, temos cerca de 1 milhão de permutações disso para armazenar de alguma forma no banco de dados. A maneira mais simples que posso pensar é ter uma coluna para cada parâmetro, com uma coluna adicional para minha chave primária (ExperimentID). Eu poderia acessar os parâmetros de um determinado experimento diretamente fazendo um simples

SELECT * FROM Parameters WHERE ExperimentID = (givenID)

Cada parâmetro será armazenado no banco de dados como um int, que será interpretado pelo meu aplicativo como os parâmetros necessários em tempo de execução.

Uma maneira mais complexa, mas acho que mais rápida, de fazer isso é aproveitar a velocidade do deslocamento binário. Em vez de armazenar os parâmetros diretamente, eu armazenaria as informações sobre cada parâmetro em 4 bits de um unsigned int. Na verdade, não sei como os ints são armazenados (em termos binários) no banco de dados, então esse é o principal obstáculo.

Algum conselho sobre o que fazer nesta situação? Além disso, ainda não tenho essas colunas, portanto, se decidisse pela primeira opção, como preencheria uma tabela com todas as permutações de um conjunto de parâmetros?

sql-server
  • 2 2 respostas
  • 829 Views

2 respostas

  • Voted
  1. Best Answer
    Solomon Rutzky
    2015-10-02T16:56:56+08:002015-10-02T16:56:56+08:00

    Por que você acha que obscurecer dados reais em um campo mascarado por bits será mais rápido? Você está falando apenas de 1 milhão de linhas e 24 bytes por linha. Isso realmente não é muito, especialmente porque você está apenas fazendo operações singleton / seek.

    Uma otimização melhor seria usar TINYINTcampos (intervalo de 0 - 255 ; byteem .NET). Usando TINYINTem vez de INT(e assumindo um FILLFACTOR** de 100) resultaria em:

    • a tabela teria efetivamente 10 MB em vez de 28 MB (1 byte para cada um dos 6 campos + 4 bytes para o campo INT [ID] = 10 bytes por linha).
    • você obteria 806 linhas por página de dados de 8060 bytes em vez de 287 com seis INTcampos

    As principais eficiências obtidas aqui são:

    • tempo de pesquisa inicial mais rápido para 2244 registros. Como assim? Com 1 milhão de linhas, 287 linhas por página de dados de 8k equivalem a 3484 páginas, enquanto 806 linhas por página de dados de 8k equivalem a apenas 1240 páginas. Depois que uma página é lida para obter os valores da primeira linha, ela deve permanecer no buffer pool (ou seja, memória) para pesquisas subsequentes (ou seja, as outras linhas na mesma página de dados). Mais linhas por página significa menos páginas para ler do disco--2244 páginas a menos neste caso. Mas uma vez que todas as páginas estão no buffer pool, as pesquisas devem ter a mesma velocidade, sejam 806 linhas ou 287 linhas por página. Portanto, 2.244 operações de pesquisa em 1 milhão são um pouco mais rápidas. Certamente nada mal, pois não houve custo associado a essa otimização, mas apenas queria que fosse colocado em perspectiva.

    • menos memória necessária para manter a tabela inteira na memória. isso fará com que seja mais provável que permaneça na memória.

    Por fim, é definitivamente possível espremer esses dados em uma representação ainda menor. Mas neste ponto são 10 bytes por linha sem nenhuma complicação adicionada ao processamento/codificação e todos os valores são legíveis por humanos. Não há muito espaço para ir abaixo de 10 bytes por linha, mas mesmo que caia para 7 bytes por linha (INT IDENTIDADE + 3 bytes para Parâmetros, que deve ser o mínimo necessário para lidar com esses intervalos), estou não tenho certeza se a complexidade adicional valeria a pena (ou seja, deseconomias de escala).


    CREATE TABLE dbo.Experiment
    (
      ExperimentID INT NOT NULL IDENTITY(1, 1),
      Parameter1  TINYINT NOT NULL,
      Parameter2  TINYINT NOT NULL,
      Parameter3  TINYINT NOT NULL,
      Parameter4  TINYINT NOT NULL,
      Parameter5  TINYINT NOT NULL,
      Parameter6  TINYINT NOT NULL,
      CONSTRAINT [PK_Experiment] PRIMARY KEY (ExperimentID) WITH (FILLFACTOR = 100) ON [Tables]
    )
    ON [Tables];
    

    E você pode preenchê-lo usando o seguinte (que assume dois parâmetros de 0 - 4, dois parâmetros de 0 - 7 e dois parâmetros de 0 - 9 ; com base nos comentários da pergunta):

    ;WITH Five(num) AS
    (
      SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4
    ), Eight(num) AS
    (
      SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4
      UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7
    ), Ten(num) AS
    (
      SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4
      UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8
      UNION ALL SELECT 9
    )
    --INSERT INTO dbo.Experiment
    --     (Parameter1, Parameter2, Parameter3, Parameter4, Parameter5, Parameter6)
    SELECT f1.[num] AS [Parameter1],
           f2.[num] AS [Parameter2],
           e1.[num] AS [Parameter3],
           e2.[num] AS [Parameter4],
           t1.[num] AS [Parameter5],
           t2.[num] AS [Parameter6]
    FROM   Five f1
    CROSS JOIN Five f2
    CROSS JOIN Eight e1
    CROSS JOIN Eight e2
    CROSS JOIN Ten t1
    CROSS JOIN Ten t2;
    

    A consulta acima gera apenas 160 mil permutações, não 1 milhão, novamente com base nos comentários da Questão. Mas deve ser bastante fácil descobrir como ajustá-lo para diferentes intervalos de valores para qualquer combinação dos seis parâmetros.


    ** FILLFACTOR: As linhas são armazenadas em páginas de dados com aproximadamente 8060 bytes. Linhas menores = mais linhas que cabem nesse contêiner de tamanho fixo. FILLFACTORé quanto espaço reservar (ao criar/reconstruir um índice) para novas linhas ou atualizações que ocupam mais espaço devido a campos de comprimento variável que requerem mais bytes para a nova versão da linha. Um valor de 100 significa que não há espaço reservado, que 100% do 8060 deve ser ocupado pelas linhas atuais. Nesse cenário, há apenas campos de comprimento fixo e nenhuma inserção fora da sequência.

    • 8
  2. Hannah Vernon
    2015-10-02T18:21:36+08:002015-10-02T18:21:36+08:00

    Gosto da ideia de armazenar os parâmetros de teste em uma única INTcoluna. Com isso em mente, criei o seguinte test-bed que pode ajudar a explicar como criar a tabela com os parâmetros de teste e como extrair esses valores posteriormente.

    Primeiro, criamos 3 tabelas que usaremos para construir os conjuntos 0-4, 0-7 e 0-9.

    CREATE TABLE dbo.numbers4 
    (
        num INT NOT NULL
    );
    CREATE TABLE dbo.numbers7 
    (
        num INT NOT NULL
    );
    CREATE TABLE dbo.numbers9 
    (
        num INT NOT NULL
    );
    

    Aqui, preenchemos as tabelas:

    INSERT INTO dbo.numbers4 (num)
    SELECT TOP(5) (ROW_NUMBER() OVER (ORDER BY o.name)) - 1
    FROM syscolumns o;
    
    INSERT INTO dbo.numbers7 (num)
    SELECT TOP(8) (ROW_NUMBER() OVER (ORDER BY o.name)) - 1
    FROM syscolumns o;
    
    INSERT INTO dbo.numbers9 (num)
    SELECT TOP(10) (ROW_NUMBER() OVER (ORDER BY o.name)) - 1
    FROM syscolumns o;
    

    Esta é a tabela que usaremos para armazenar os INTvalores de deslocamento de bits combinando os 6 conjuntos de números:

    CREATE TABLE dbo.t
    (
        TestID INT NOT NULL
            CONSTRAINT PK_t
            PRIMARY KEY CLUSTERED
            IDENTITY(1,1)
        , TestParms INT NOT NULL
    );
    

    E aqui preenchemos essa tabela das 3 tabelas temporárias acima:

    DECLARE @p1 INT;
    DECLARE @p2 INT;
    DECLARE @p3 INT;
    DECLARE @p4 INT;
    DECLARE @p5 INT;
    DECLARE @p6 INT;
    
    SET @p1 = 0x1;
    SET @p2 = 0x10;
    SET @p3 = 0x100;
    SET @p4 = 0x1000;
    SET @p5 = 0x10000;
    SET @p6 = 0x100000;
    
    TRUNCATE TABLE dbo.t;
    
    INSERT INTO dbo.t (TestParms)
    SELECT (n1.num
        + n2.num * @p2
        + n3.num * @p3
        + n4.num * @p4
        + n5.num * @p5
        + n6.num * @p6)
    FROM dbo.numbers4 n1 
        , dbo.numbers4 n2
        , dbo.numbers7 n3
        , dbo.numbers7 n4
        , dbo.numbers9 n5
        , dbo.numbers9 n6;
    

    Esta próxima parte mostra como extrair os números em 6 conjuntos diferentes de uma única INTcoluna:

    DECLARE @p1 INT;
    DECLARE @p2 INT;
    DECLARE @p3 INT;
    DECLARE @p4 INT;
    DECLARE @p5 INT;
    DECLARE @p6 INT;
    
    SET @p1 = 0xF;
    SET @p2 = 0xFF;
    SET @p3 = 0xFFF;
    SET @p4 = 0xFFFF;
    SET @p5 = 0xFFFFF;
    SET @p6 = 0xFFFFFF;
    
    DECLARE @p1_shift INT;
    DECLARE @p2_shift INT;
    DECLARE @p3_shift INT;
    DECLARE @p4_shift INT;
    DECLARE @p5_shift INT;
    DECLARE @p6_shift INT;
    
    SET @p1_shift = 0x1;
    SET @p2_shift = 0x10;
    SET @p3_shift = 0x100;
    SET @p4_shift = 0x1000;
    SET @p5_shift = 0x10000;
    SET @p6_shift = 0x100000;
    
    SELECT t.TestID
        , Param1 = (t.TestParms & @p1)
        , Param2 = (t.TestParms & @p2) / @p2_shift
        , Param3 = (t.TestParms & @p3) / @p3_shift
        , Param4 = (t.TestParms & @p4) / @p4_shift
        , Param5 = (t.TestParms & @p5) / @p5_shift
        , Param6 = (t.TestParms & @p6) / @p6_shift
    FROM dbo.t t;
    

    Como existem apenas 160.000 linhas (o número de permutações que você sugere), esta tabela requer apenas 2,6 MB de espaço de armazenamento (aproximadamente 330 páginas de dados), incluindo a IDENTITYcoluna, que pode ou não ser necessária.

    Uma amostra dos resultados selectacima são:

    insira a descrição da imagem aqui

    • 1

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

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

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

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