it-swarm-eu.dev

Je možné mysqldump podmnožinu databáze potřebné k reprodukci dotazu?

Pozadí

Chtěl bych poskytnout podmnožinu mé databáze potřebné k reprodukci dotazu select. Mým cílem je, aby byl můj výpočetní tok práce reprodukovatelný (jako v reprodukovatelný výzkum ).

Otázka

Existuje způsob, jak mohu začlenit tento příkaz select do skriptu, který vypíše dotazovaná data do nové databáze, takže databáze by mohla být nainstalována na nový server mysql a příkaz by pracoval s novou databází. Nová databáze by neměla obsahovat záznamy kromě těch, které byly použity v dotazu.

Aktualizace: Pro vyjasnění mě nezajímá výpis výsledků CSV. Co musím udělat, je vypsat podmnožinu databáze, aby mohla být nainstalována na jiném počítači, a pak samotný dotaz může být reprodukovatelný (a upravitelný s ohledem na stejný datový soubor).

Příklad

Moje analýza může například dotazovat podmnožinu dat, která vyžaduje záznamy z více (v tomto příkladu 3) tabulek:

select table1.id, table1.level, table2.name, table2.level 
       from table1 join table2 on table1.id = table2.table1_id 
       join table3 on table3.id = table2.table3_id
       where table3.name in ('fee', 'fi', 'fo', 'fum'); 
38
David LeBauer

mysqldump má možnost - where provést klauzuli WHERE pro danou tabulku.

Ačkoli není možné mysqldump dotaz na spojení, můžete exportovat konkrétní řádky z každé tabulky, takže každý řádek načtený z každé tabulky bude později zapojen do spojení.

Pro zadaný dotaz byste museli mysqldump třikrát:

Nejprve mysqldump všechny řádky tabulky 3 se jménem v ('poplatek', 'fi', 'fo', 'fum'):

mysqldump -u... -p... --where="name in ('fee','fi','fo','fum')" mydb table3 > table3.sql

Dále mysqldump všechny řádky table2, které mají shodné hodnoty table3_id z prvního mysqldump:

mysqldump -u... -p... --lock-all-tables --where="table3_id in (select id from table3 where name in ('fee','fi','fo','fum'))" mydb table2 > table2.sql

Potom mysqldump všechny řádky table1, které mají odpovídající hodnoty table1_id z druhého mysqldump:

mysqldump -u... -p... --lock-all-tables --where="id in (select table1_id from table2 where table3_id in (select id from table3 where name in ('fee','fi','fo','fum')))" mydb table1 > table1.sql

Poznámka: Protože druhá a třetí mysqldumps vyžadují použití více než jedné tabulky, je třeba použít --lock-all-tables .

Vytvořte novou databázi:

mysqladmin -u... -p... mysqladmin create newdb

Nakonec načtěte tři mysqldumps do jiné databáze a zkuste se tam připojit v nové databázi.

mysql -u... -p... -D newdb < table1.sql
mysql -u... -p... -D newdb < table2.sql
mysql -u... -p... -D newdb < table3.sql

V klientovi mysql spusťte dotaz na spojení

mysql> use newdb
mysql> select table1.id, table1.level, table2.name, table2.level 
       from table1 join table2 on table1.id = table2.table1_id 
       join table3 on table3.id = table2.table3_id
       where table3.name in ('fee', 'fi', 'fo', 'fum'); 

Pokusit se !!!

VAROVÁNÍ: Pokud není správně indexována, může druhá a třetí mysqldumps trvat věčně !!!

Pouze pro případ, indexujte následující sloupce:

ALTER TABLE table2 ADD INDEX (table1_id);
ALTER TABLE table2 ADD INDEX (table3_id);
ALTER TABLE table3 ADD INDEX (name,id);

Předpokládám, že id je primární klíč tabulky3.

55
RolandoMySQLDBA

K vyřešení tohoto problému bych považoval pomocí 'outfile' jako součást vašeho SELECT namísto mysqldump. Můžete vytvořit libovolný příkaz SELECT a poté připojit „INTO OUTFILE '/path/to/outfile.csv' ..." na konci s odpovídající konfigurací pro výstup ve stylu CSV. Pak můžete jednoduše použít něco jako ' LOAD DATA INFILE ...' syntaxe pro načtení dat do vašeho nového umístění schématu.

Například pomocí SQL:

select table1.id, table1.level, table2.name, table2.level 
       from table1 join table2 on table1.id = table2.table1_id 
       join table3 on table3.id = table2.table3_id
       where table3.name in ('fee', 'fi', 'fo', 'fum')
INTO OUTFILE '/tmp/fee-fi-fo-fum.csv'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
; 

Nezapomeňte, že budete potřebovat dostatek volného místa v cílovém diskovém oddílu.

7
randomx

Utilita mysqldump má - možnost tabulky , která vám umožní určit, které tabulky se mají vypsat. Umožňuje určit seznam tabulek.

Nevím o žádné jednodušší (automatizované) cestě.

6
Richard

Co pro mě bylo užitečné, bylo něco jako:

mysqldump -u db_user -p db_name table_name --no_create_info \
--lock-all-tables --where 'id in (SELECT tn.id FROM table_name AS tn \
JOIN related_table AS rt ON tn.related_table_id = rt.id \
WHERE rt.some_field = 1)' > data.sql

Od http://krosinski.blogspot.com/2012/12/using-table-join-with-mysqldump.html

3
Ryan

Vyzkoušeli jste funkci citace v mysql?

SELECT CONCAT("insert into table4(id,level,name,levelt2) VALUES(",   quote(table1.id),   ",",    quote(table1.level),   ",",    quote(table2.name),   ",",    quote(table2.level),    ");") as q
       from table1 join table2 on table1.id = table2.table1_id 
       join table3 on table3.id = table2.table3_id
       where table3.name in ('fee', 'fi', 'fo', 'fum'); 

uložte výše, jako query.sql

cat query.sql|mysql --skip-column-names --raw > table4.sql
2
velcrow

napsal jsem malý skript pro podobný problém, tady to je: https://github.com/digitalist/mysql_slice

include ('queryDumper.php');


$exampleQuery="select * from information_schema.columns c1 
left join information_schema.columns c2 on 1=1 limit 1";

//define credentials
$exampleMysqli = new mysqli($Host, $user, $password, $database);
$exampleResult=$exampleMysqli->query($exampleQuery);

//if  mysqlnd (native driver installed), otherwise use wrapper
$exampleData=fetchAll($exampleResult);
$exampleMeta=$exampleResult->fetch_fields();

/*
 * field content removal options
 * column name => function name in queryDumper.php, namespace QueryDumperHelpers
 * 
 * */

$forbiddenFields=array(
'password'=>'replacePassword', //change password -> md5("password")
'login'=>'replaceLogin', //change login [email protected] -> [email protected]
'comment'=>'sanitizeComment' //lorem ipsum or 
);


//get tables dump
$dump=(\queryDumper\dump($exampleData, $exampleMeta, $forbiddenFields));



$dropDatabase=true; //default false
$dropTable=true; //default false

$dbAndTablesCreationDump=\QueryDumperDatabaseAndTables\dump($exampleMysqli,$exampleMeta, $dropDatabase, $dropTable);

$databases=$dbAndTablesCreationDump['databases'];
$tables=$dbAndTablesCreationDump['tables'];
$eol=";\n\n";
echo implode($eol, $databases)."\n";
echo implode($eol, $tables).";\n";
echo "\n";

//consider using array_unique($dump) before imploding
echo implode("\n\n", $dump);
echo "\n";
?>

tj. máte tento dotaz :

SELECT * FROM employees.employees e1 
LEFT JOIN employees.employees e2 ON 1=1 
LIMIT 1; 

jste dostali tento výpis :

DROP DATABASE `employees`;

CREATE DATABASE `employees`;
CREATE TABLE `employees` ( /* creation code */ ) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT IGNORE INTO `employees`.`employees` VALUES ("10001","1953-09-02","Georgi","Facello","M","1986-06-26");

INSERT IGNORE INTO `employees`.`employees` VALUES ("10001","1953-09-02","Georgi","Facello","M","1986-06-26");
1
digitalist

V MySQL:

SHOW CREATE TABLE table1; -- use these two create statements
SHOW CREATE TABLE table2; -- to design table4's create statement
CREATE TABLE table4( .... );
INSERT INTO table4(id,level,name,levelt2)
SELECT table1.id, table1.level, table2.name, table2.level 
   from table1 join table2 on table1.id = table2.table1_id 
   join table3 on table3.id = table2.table3_id
   where table3.name in ('fee', 'fi', 'fo', 'fum'); 

Na příkazovém řádku:

mysqldump mydb table4 |gzip > table4.sql.gz

Na cílovém serveru nastavte ~/.my.cnf

[client]
default-character-set=utf8

Importovat na cílovém serveru

zcat table4.sql.gz | mysql
1
velcrow