mdbq 3.12.1__py3-none-any.whl → 3.12.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mdbq/__version__.py +1 -1
- mdbq/mysql/deduplicator.py +65 -40
- mdbq/mysql/uploader.py +1 -1
- {mdbq-3.12.1.dist-info → mdbq-3.12.3.dist-info}/METADATA +1 -1
- {mdbq-3.12.1.dist-info → mdbq-3.12.3.dist-info}/RECORD +7 -7
- {mdbq-3.12.1.dist-info → mdbq-3.12.3.dist-info}/WHEEL +0 -0
- {mdbq-3.12.1.dist-info → mdbq-3.12.3.dist-info}/top_level.txt +0 -0
mdbq/__version__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
VERSION = '3.12.
|
1
|
+
VERSION = '3.12.3'
|
mdbq/mysql/deduplicator.py
CHANGED
@@ -21,7 +21,7 @@ warnings.filterwarnings('ignore')
|
|
21
21
|
logger = mylogger.MyLogger(
|
22
22
|
name='deduplicator',
|
23
23
|
logging_mode='file',
|
24
|
-
log_level='
|
24
|
+
log_level='debug',
|
25
25
|
log_file='deduplicator.log',
|
26
26
|
log_format='json',
|
27
27
|
max_log_size=50,
|
@@ -34,7 +34,22 @@ logger = mylogger.MyLogger(
|
|
34
34
|
|
35
35
|
class MySQLDeduplicator:
|
36
36
|
"""
|
37
|
-
MySQL
|
37
|
+
MySQL 数据去重。
|
38
|
+
|
39
|
+
支持按天分区(如有 date_column)或全表去重,支持自定义去重分组字段(columns),可排除指定列(exclude_columns),并支持多线程并发。
|
40
|
+
|
41
|
+
主要参数说明:
|
42
|
+
- columns: 指定去重分组字段,控制唯一性分组行为。若 columns 有值且不包含 date_column,则全表去重,否则按天分区。
|
43
|
+
- exclude_columns: 去重时排除的列名列表,自动合并 ['id', '更新时间'],在分组时排除。
|
44
|
+
- date_column: 指定日期分区字段,默认为 '日期'。如表存在该字段且 columns 未排除,则按天分区去重。
|
45
|
+
- duplicate_keep_mode: 'keep_one'(默认,重复组保留一条),'remove_all'(全部删除重复组)。
|
46
|
+
- dry_run: 是否为模拟运行,不实际删除数据。
|
47
|
+
- use_python_dedup: 是否用 Python 方式去重(否则用 SQL)。
|
48
|
+
|
49
|
+
分天/全表去重行为:
|
50
|
+
- 若 columns 有值且不包含 date_column,则直接全表去重,分组字段为 columns。
|
51
|
+
- 否则,若表存在 date_column,则按天分区去重,分组字段为 columns(如有)或全表字段。
|
52
|
+
- exclude_columns 始终生效,分组时自动排除。
|
38
53
|
"""
|
39
54
|
|
40
55
|
def __init__(
|
@@ -370,15 +385,17 @@ class MySQLDeduplicator:
|
|
370
385
|
lock_table: bool = True
|
371
386
|
) -> Tuple[int, int]:
|
372
387
|
"""
|
373
|
-
|
374
|
-
|
388
|
+
执行单表单天或全表去重。根据 columns 和 date_column 决定分天或全表:
|
389
|
+
- 若 columns 不包含 date_column,则全表去重(不分天)。
|
390
|
+
- 若 columns 包含 date_column 或未指定 columns,则按天分区去重(date_val 为当前处理日期)。
|
391
|
+
|
375
392
|
Args:
|
376
393
|
database (str): 数据库名。
|
377
394
|
table (str): 表名。
|
378
|
-
columns (Optional[List[str]]):
|
395
|
+
columns (Optional[List[str]]): 指定去重列。若不含 date_column,则全表去重。
|
379
396
|
dry_run (bool): 是否为模拟运行。
|
380
397
|
use_python_dedup (bool): 是否用 Python 方式去重。
|
381
|
-
date_val (Optional[str]): 指定处理的日期(如有 date_column
|
398
|
+
date_val (Optional[str]): 指定处理的日期(如有 date_column 且分天时)。
|
382
399
|
lock_table (bool): 是否加表级锁。
|
383
400
|
Returns:
|
384
401
|
Tuple[int, int]: (重复组数, 实际删除行数)
|
@@ -392,13 +409,12 @@ class MySQLDeduplicator:
|
|
392
409
|
exclude_columns_lower = [col.lower() for col in getattr(self, 'exclude_columns', [])]
|
393
410
|
time_col = self.date_column
|
394
411
|
time_col_lower = time_col.lower() if time_col else None
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
if has_time_col and date_val is not None:
|
412
|
+
# 如果传了columns且columns不包含date_column,则不分天,直接全表去重
|
413
|
+
if columns and (not time_col_lower or time_col_lower not in [c.lower() for c in columns]):
|
414
|
+
has_time_col = False # 全表去重
|
415
|
+
else:
|
416
|
+
has_time_col = time_col_lower in all_columns_lower if time_col_lower else False # 分天去重
|
417
|
+
if has_time_col:
|
402
418
|
self._ensure_index(database, table, time_col)
|
403
419
|
# 获取去重列
|
404
420
|
use_columns = columns or all_columns
|
@@ -442,14 +458,11 @@ class MySQLDeduplicator:
|
|
442
458
|
if not dry_run and del_ids:
|
443
459
|
with self._conn_ctx() as conn:
|
444
460
|
with conn.cursor() as cursor:
|
445
|
-
for i in
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
batch_deleted = cursor.rowcount
|
451
|
-
affected_rows += batch_deleted
|
452
|
-
conn.commit()
|
461
|
+
format_ids = ','.join([str(i) for i in del_ids])
|
462
|
+
del_sql = f"DELETE FROM `{database}`.`{table}` WHERE `{pk_real}` IN ({format_ids})"
|
463
|
+
cursor.execute(del_sql)
|
464
|
+
affected_rows = cursor.rowcount
|
465
|
+
conn.commit()
|
453
466
|
logger.debug('去重完成', {"库": database, "表": table, "数据量": total_count, "重复组": dup_count, "实际删除": affected_rows, "去重方式": "Python", "数据处理": self.duplicate_keep_mode, "数据日期": date_val})
|
454
467
|
return (dup_count, affected_rows)
|
455
468
|
# SQL方式查找重复
|
@@ -652,12 +665,20 @@ class MySQLDeduplicator:
|
|
652
665
|
use_python_dedup: bool = True
|
653
666
|
) -> Tuple[int, int]:
|
654
667
|
"""
|
655
|
-
|
656
|
-
|
668
|
+
对指定表进行去重。
|
669
|
+
|
670
|
+
去重行为说明:
|
671
|
+
- 若 columns 参数传入且不包含 date_column,则全表直接按 columns 去重。
|
672
|
+
- 若 columns 包含 date_column 或未指定 columns,则按天分区去重(每一天独立去重)。
|
673
|
+
- exclude_columns 中的字段始终不会参与去重分组。
|
674
|
+
- date_column 默认为 '日期',可自定义。
|
675
|
+
- dry_run 模式下仅统计重复组和待删除行数,不实际删除。
|
676
|
+
- reorder_id=True 时,去重后自动重排主键 id。
|
677
|
+
|
657
678
|
Args:
|
658
679
|
database (str): 数据库名。
|
659
680
|
table (str): 表名。
|
660
|
-
columns (Optional[List[str]]):
|
681
|
+
columns (Optional[List[str]]): 指定去重列。若不含 date_column,则全表去重。
|
661
682
|
dry_run (bool): 是否为模拟运行。
|
662
683
|
reorder_id (bool): 去重后是否自动重排 id 列。
|
663
684
|
use_python_dedup (bool): 是否用 Python 方式去重。
|
@@ -686,7 +707,11 @@ class MySQLDeduplicator:
|
|
686
707
|
all_columns_lower = [col.lower() for col in all_columns]
|
687
708
|
time_col = self.date_column
|
688
709
|
time_col_lower = time_col.lower() if time_col else None
|
689
|
-
|
710
|
+
# 如果传了columns且columns不包含date_column,则不分天,直接全表去重
|
711
|
+
if columns and (not time_col_lower or time_col_lower not in [c.lower() for c in columns]):
|
712
|
+
has_time_col = False # 全表去重
|
713
|
+
else:
|
714
|
+
has_time_col = time_col_lower in all_columns_lower if time_col_lower else False # 分天去重
|
690
715
|
if has_time_col:
|
691
716
|
self._ensure_index(database, table, time_col)
|
692
717
|
all_dates = self._get_all_dates(database, table, time_col)
|
@@ -1299,30 +1324,30 @@ def main():
|
|
1299
1324
|
skip_system_dbs=True,
|
1300
1325
|
max_retries=3,
|
1301
1326
|
retry_waiting_time=5,
|
1302
|
-
|
1327
|
+
pool_size=30,
|
1303
1328
|
recent_month=1,
|
1304
1329
|
# date_range=['2025-06-09', '2025-06-10'],
|
1305
|
-
|
1306
|
-
exclude_databases=['测试库4'],
|
1307
|
-
exclude_tables={
|
1308
|
-
|
1309
|
-
|
1310
|
-
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
|
1315
|
-
},
|
1330
|
+
exclude_columns=['更新时间'],
|
1331
|
+
# exclude_databases=['测试库4'],
|
1332
|
+
# exclude_tables={
|
1333
|
+
# '推广数据2': [
|
1334
|
+
# '地域报表_城市_2025_04',
|
1335
|
+
# # '地域报表_城市_2025_04_copy1',
|
1336
|
+
# ],
|
1337
|
+
# "生意参谋3": [
|
1338
|
+
# "商品排行_2025",
|
1339
|
+
# ],
|
1340
|
+
# },
|
1316
1341
|
)
|
1317
1342
|
|
1318
1343
|
# 全库去重(单线程)
|
1319
|
-
deduplicator.deduplicate_all(dry_run=False, parallel=True, reorder_id=True)
|
1344
|
+
# deduplicator.deduplicate_all(dry_run=False, parallel=True, reorder_id=True)
|
1320
1345
|
|
1321
1346
|
# # 指定数据库去重(多线程)
|
1322
|
-
# deduplicator.deduplicate_database('
|
1347
|
+
# deduplicator.deduplicate_database('数据引擎2', dry_run=False, parallel=True, reorder_id=True)
|
1323
1348
|
|
1324
1349
|
# # 指定表去重(使用特定列)
|
1325
|
-
|
1350
|
+
deduplicator.deduplicate_table('安全组', '腾讯云cvm规则', columns=['平台', '本地主机', '端口范围', '授权ip'], dry_run=False, reorder_id=True)
|
1326
1351
|
|
1327
1352
|
# # 重排id列
|
1328
1353
|
# deduplicator.reorder_id_column('my_db', 'my_table', 'id', dry_run=False, auto_drop_backup=True)
|
mdbq/mysql/uploader.py
CHANGED
@@ -1573,7 +1573,7 @@ def main():
|
|
1573
1573
|
partition_date_column='日期', # 用于分表的日期列名,默认为'日期'
|
1574
1574
|
indexes=[], # 普通索引列
|
1575
1575
|
transaction_mode='row', # 事务模式
|
1576
|
-
unique_keys=[['日期', 'name', 'age']] # 唯一约束列表
|
1576
|
+
unique_keys=[['日期', 'name', 'age']], # 唯一约束列表
|
1577
1577
|
)
|
1578
1578
|
|
1579
1579
|
uploader.close()
|
@@ -1,5 +1,5 @@
|
|
1
1
|
mdbq/__init__.py,sha256=Il5Q9ATdX8yXqVxtP_nYqUhExzxPC_qk_WXQ_4h0exg,16
|
2
|
-
mdbq/__version__.py,sha256=
|
2
|
+
mdbq/__version__.py,sha256=9x3pJeqVdjIfn83Ln01YuTBiHKPCTeK3xkXQT4NcYno,18
|
3
3
|
mdbq/aggregation/__init__.py,sha256=EeDqX2Aml6SPx8363J-v1lz0EcZtgwIBYyCJV6CcEDU,40
|
4
4
|
mdbq/aggregation/query_data.py,sha256=nxL8hSy8yI1QLlqnkTNHHQSxRfo-6WKL5OA-N4xLB7c,179832
|
5
5
|
mdbq/config/__init__.py,sha256=jso1oHcy6cJEfa7udS_9uO5X6kZLoPBF8l3wCYmr5dM,18
|
@@ -8,10 +8,10 @@ mdbq/log/__init__.py,sha256=Mpbrav0s0ifLL7lVDAuePEi1hJKiSHhxcv1byBKDl5E,15
|
|
8
8
|
mdbq/log/mylogger.py,sha256=Crw6LwVo3I3IUbzIETu8f46Quza3CTCh-qYf4edbBPo,24139
|
9
9
|
mdbq/log/spider_logging.py,sha256=-ozWWEGm3HVv604ozs_OOvVwumjokmUPwbaodesUrPY,1664
|
10
10
|
mdbq/mysql/__init__.py,sha256=A_DPJyAoEvTSFojiI2e94zP0FKtCkkwKP1kYUCSyQzo,11
|
11
|
-
mdbq/mysql/deduplicator.py,sha256=
|
11
|
+
mdbq/mysql/deduplicator.py,sha256=uBRM2cBF-gzkFFrmBSKqBd_LLO-K67LYUJqpF9Fs928,70561
|
12
12
|
mdbq/mysql/mysql.py,sha256=Kjpi-LL00WQUmTTOfhEBsNrmo4-4kFFJzrHbVKfqiBE,56770
|
13
13
|
mdbq/mysql/s_query.py,sha256=dlnrVJ3-Vp1Suv9CNbPxyYSRqRJUHjOpF39tb2F-wBc,10190
|
14
|
-
mdbq/mysql/uploader.py,sha256=
|
14
|
+
mdbq/mysql/uploader.py,sha256=szX6t4SObBF6fbHT2s5ixfh1-c288cigsJ66pFE02Qg,70266
|
15
15
|
mdbq/other/__init__.py,sha256=jso1oHcy6cJEfa7udS_9uO5X6kZLoPBF8l3wCYmr5dM,18
|
16
16
|
mdbq/other/download_sku_picture.py,sha256=YU8DxKMXbdeE1OOKEA848WVp62jYHw5O4tXTjUdq9H0,44832
|
17
17
|
mdbq/other/otk.py,sha256=iclBIFbQbhlqzUbcMMoePXBpcP1eZ06ZtjnhcA_EbmE,7241
|
@@ -24,7 +24,7 @@ mdbq/redis/__init__.py,sha256=YtgBlVSMDphtpwYX248wGge1x-Ex_mMufz4-8W0XRmA,12
|
|
24
24
|
mdbq/redis/getredis.py,sha256=YHgCKO8mEsslwet33K5tGss-nrDDwPnOSlhA9iBu0jY,24078
|
25
25
|
mdbq/spider/__init__.py,sha256=RBMFXGy_jd1HXZhngB2T2XTvJqki8P_Fr-pBcwijnew,18
|
26
26
|
mdbq/spider/aikucun.py,sha256=cqK-JRd_DHbToC7hyo83m8o97NZkJFqmB2xBtr6aAVU,20961
|
27
|
-
mdbq-3.12.
|
28
|
-
mdbq-3.12.
|
29
|
-
mdbq-3.12.
|
30
|
-
mdbq-3.12.
|
27
|
+
mdbq-3.12.3.dist-info/METADATA,sha256=kkujbmKfbA4mOHCloHBALjK3jI2sNoft1yyHmpbnmoI,364
|
28
|
+
mdbq-3.12.3.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
|
29
|
+
mdbq-3.12.3.dist-info/top_level.txt,sha256=2FQ-uLnCSB-OwFiWntzmwosW3X2Xqsg0ewh1axsaylA,5
|
30
|
+
mdbq-3.12.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|