欢迎来到好人卡资源网,专注网络技术资源收集,我们不仅是网络资源的搬运工,也生产原创资源。寻找资源请留言或关注公众号:烈日下的男人

最近流出的各种数据社工Q库优化教程

linux sky995 3年前 (2021-10-09) 896次浏览 0个评论

本文及资源最后更新时间 2021-10-10 by sky995

以qq库为例:

得到的数据源文件为txt无序数据

step1: 对源文件进行分割合并排序 key为qq字段(phone也行)

这里我自己写了一个脚本,需要配合emeditor

使用emeditor将源文件以行分割 7k5w行一个文件 分出来大概10个文件

对这是个文件进行归并排序,最后得到的需要是一个有序的源文件

step2: 使用emeditor将源文件以行分割 100w行一个文件  分割后大概720个文件

为后面建表作为数据源,每个文件对应一张表,也就是720张表

step3: 批量创建数据库导入数据

先建立一个用于查询数据库名的表,字段为 database_name,begin,end

begin,end对应每个排序表的开始和结尾

这里以linux系统为例: 批量创建database及压缩表(压缩表可以减少表的占用空间和提高查询效率)

注意下压缩表不能修改,这里贴下shell脚本,需要有一定的基础,进行修改

  1. #!/bin/bash
  2. index=1
  3. USER_NAME="root"
  4. PASSWD=""
  5. DB_NAME=""
  6. HOST_NAME="127.0.0.1"
  7. DB_PORT="3306"
  8. endIndex=720
  9. MYSQL_ETL="mysql -h${HOST_NAME} -P${DB_PORT} -u${USER_NAME} -p${PASSWD} ${DB_NAME} -s -e"
  10. for ((i=$index; i<=$endIndex; i++))
  11.     do
  12.         table_name="qq_database_"$i""
  13.         database_path="/var/lib/mysql-files/qq_database/MargedFileOutPut_"$i".txt"
  14.         times=$(date "+%Y-%m-%d %H:%M:%S")
  15.         echo "[${times}] Insert Data ${table_name}"
  16.         create_table="CREATE TABLE ${table_name}  ( qq bigint UNSIGNED NOT NULL,phone bigint UNSIGNED NOT NULL,PRIMARY KEY (qq), INDEX phone_index(phone) USING BTREE) ENGINE = MyISAM;"
  17.         exec_create_table=$($MYSQL_ETL "${create_table}")
  18.         load_data="LOAD DATA INFILE '${database_path}' REPLACE INTO TABLE "${table_name}" FIELDS TERMINATED BY ',' enclosed by '' lines terminated by '\n' (qq,phone);"
  19.         exec_load_data=$($MYSQL_ETL "${load_data}")
  20.         query_begin="select * from ${table_name} limit 1;"
  21.         query_end="select * from ${table_name} order by qq desc limit 1;"
  22.         query_begin_done=$($MYSQL_ETL "${query_begin}")
  23.         query_end_done=$($MYSQL_ETL "${query_end}")
  24.         array=(${query_begin_done// / })
  25.         begin=${array[0]}
  26.         array=(${query_end_done// / })
  27.         end=${array[0]}
  28.         insert_index="INSERT INTO qq_database_index (database_name, begin, end) VALUES ('${table_name}',${begin},${end});"
  29.         insert_index_done=$($MYSQL_ETL "${insert_index}")
  30.         #pack
  31.         myisampack /var/lib/mysql/bind_search_service/${table_name}
  32.         myisamchk -rq /var/lib/mysql/bind_search_service/${table_name}
  33.         #update
  34.         #remove file
  35.         > /boot/bigfile
  36.         rm ${database_path}
  37.         times=$(date "+%Y-%m-%d %H:%M:%S")
  38.         echo "[${times}] Insert Data ${table_name} Done!"
  39. done

step4:
脚本运行完后需要刷新下表,flush tables;

step5: 查询

先查询数据库索引表 通过 begin<= keys <= end进行查询,得到的数据取出数据库名

再进行一次查询 SELECT * FROM database_name WHELE qq = keys;

通过分表和添加索引,查询效率非常高且占用空间少 通过主键查询大概0.05s以内,当然如果通过索引phone查询就得需要查询所有分表

写个循环构造表名,处理好逻辑 查询时间大概也在0.5s以内,

最后贴下归并排序文件的python源码

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # [url=home.php?mod=space&uid=2260]@Time[/url]    : 2021/3/9 10:12
  4. # @Author  : Smida
  5. # @FileName: sortDatabase.py
  6. # @Software: PyCharm
  7. import os
  8. import time
  9. import numpy
  10. class SortDatabaseManager():
  11.     dataPath = "E:\\ariDownload\\裤子\\q绑\\qqSearch_split_6\\OutPut" #文件目录
  12.     dataFiles = [i for i in os.listdir(dataPath) if i[-3::] == 'txt'] #目录下所有txt文件名
  13.     theQQMaxMap = {}
  14.     theSplitFlag = ','
  15.     theDataPosition = 0
  16.     timeScale = 0
  17.     @staticmethod
  18.     def printLog(msg):
  19.         print(f"[{time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())}] -> {msg}")
  20.     @staticmethod
  21.     def caculateTimeSpan(fileSize,timeScale):
  22.         return fileSize/timeScale if timeScale else "Null"
  23.     @staticmethod
  24.     def getFileSize(filePath):
  25.         return round(os.path.getsize(filePath) / float(1024 * 1024),2)
  26.     def sortFile(self,path, chunk):
  27.         self.printLog(f"开始分割文件 {path} \n 缓存大小为{chunk}")
  28.         baseDir, baseFile = os.path.split(path)
  29.         fileIndex = 1
  30.         files = []
  31.         with open(path, 'r') as f:
  32.             while True:
  33.                 lines = f.readlines(chunk)
  34.                 lines.sort(key=lambda  x: int(x.split(",")[0]))
  35.                 if lines:
  36.                     newFileName = os.path.join(baseDir, f"{baseFile[1:-4]}_{fileIndex}.txt")
  37.                     with open(newFileName, 'a') as sf:
  38.                         sf.write(''.join(lines))
  39.                     files.append(newFileName)
  40.                     fileIndex += 1
  41.                 else:
  42.                     break
  43.         return files
  44.     def mergeFiles(self,fileList: list,filePath: str) -> str:
  45.         """
  46.         :param fileList: a list of file absolute path
  47.         :return: a string of merged file absolute path
  48.         """
  49.         self.printLog(f"开始归并文件覆盖输出到 {filePath}")
  50.         fs = [open(file_, 'r') for file_ in fileList]
  51.         tempDict = {}
  52.         mergedFile = open(filePath, 'w+')
  53.         for f in fs:
  54.             initLine = f.readline()
  55.             if initLine:
  56.                 tempDict[f] = initLine
  57.         while tempDict:
  58.             min_item = min(tempDict.items(), key=lambda x: int(x[1].split(",")[0]))
  59.             mergedFile.write(min_item[1])
  60.             nextLine = min_item[0].readline()
  61.             if nextLine:
  62.                 tempDict[min_item[0]] = nextLine
  63.             else:
  64.                 del tempDict[min_item[0]]
  65.                 min_item[0].close()
  66.         mergedFile.close()
  67.         for file_ in fileList:
  68.             self.printLog(f"清除缓存文件 {file_}")
  69.             os.remove(file_)
  70.         return os.path.join(filePath)
  71.     def getFilePaths(self):
  72.         pathList = []
  73.         for fileName in self.dataFiles:
  74.             pathList.append(f"{self.dataPath}\\{fileName}")
  75.         return pathList
  76.     def setTimeScale(self,fileSize,timeSpan):
  77.         self.timeScale = fileSize // timeSpan
  78.     # 遍历文件,找出每个文件的最大值或最小值
  79.     def startSortFile(self):
  80.         allStartTime = time.time()
  81.         filePathList = []
  82.         for fileName in self.dataFiles:
  83.             filePath = f"{self.dataPath}\\{fileName}"
  84.             if fileName == "qqSearch_1.txt":
  85.                 continue
  86.             fileSize = self.getFileSize(filePath)
  87.             startTime = time.time()
  88.             self.printLog(f"开始处理文件:{fileName} 预计耗时:{self.caculateTimeSpan(fileSize, self.timeScale)}s")
  89.             self.mergeFiles(self.sortFile(filePath,1024 * 1024 * 500),filePath)
  90.             endTime = time.time()
  91.             self.setTimeScale(fileSize,endTime - startTime)
  92.         self.printLog("开始最后归并...")
  93.         for i in self.dataFiles:
  94.             filePathList.append(f"{self.dataPath}\\{i}")
  95.         self.mergeFiles(filePathList, "MargedFileOutPut.txt")
  96.         allEndTime = time.time()
  97.         self.printLog(f"Done!  耗时{allEndTime-allStartTime}")
  98. oj = SortDatabaseManager()
  99. path = oj.startSortFile()

同qq库一样凡是可以使用bigint存储的都可以使用类似方法,在服务器配置不好的情况下,可以尝试。


好人卡资源网 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:最近流出的各种数据社工Q库优化教程
喜欢 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址