【发布时间】:2014-12-09 12:20:42
【问题描述】:
我是这个网站的新手,我在这里找到了很多答案。
我不是最好的 python 或 mysql 程序员,但我想创建一个非常简单的脚本, 它将一些信息放入数据库中,我可以在其中查找和排序,无论怎样。
我正在尝试创建类似于 DNS 请求记录器的东西。 Windows 2003(当前)服务器正在将所有 DNS 请求记录到文件中。 每天我都会将那个(新的)日志文件拉到一台 Ubuntu 机器上,以将它处理成一个 MySQL 数据库, 使用 sh 和 python。
这是我想要一些建议的部分,日志文件可能会变得很大,大约 70k 行, 使用下面的代码可以轻松处理长达 20 分钟。有什么方法可以加快速度,(我是否使用糟糕的编码)或者它是“好的”。
我试图让我的 sql 命令尽可能具体,只返回所需的内容, 每 5000 次迭代只使用一次提交
主要大纲: 检查数据库中是否存在记录,如果没有创建,则返回ID。 检查当时是否已经记录了条目(HH:MM,几乎同时注意到多个查询),如果没有创建条目,则添加 1 计数。
就是这样..
提前感谢愿意看一看的人。
尼克。
示例条目:
20141204 23:00:50 172.000.000.000 A .www.google.nl
20141204 23:00:53 172.000.000.000 AAAA .www.google.nl
代码:
#! /usr/bin/python
import os, sys
from datetime import datetime
import MySQLdb
# variables
dnslog = "dns-edited.log"
sqldb = None
sqlcur = None
def leesBestand(bestand):
with open(bestand,"r") as entries:
runcount = 0
for entry in entries:
# 0:<Datum> 1:<Tijd> 2:<IP Requester> 3:<Record Type> 4:<Domain name>
words = entry.split()
datum = setDatum(words[0])
tijd = setTijd(words[1])
domainId = checkEntry(words[4][1:],words[3])
requestId = bestaadRequest(datum,tijd,words[2],domainId)
if runcount > 5000 :
dbCommit()
runcount = 0
runcount += 1
def dbExecute(sqlstring):
try :
global sqlcur
sqlcur.execute(sqlstring)
except MySQLdb.Error,e:
global sqldb
sqldb.rollback()
print "[Error-Execute] : " + str(e)
def dbCommit():
global sqldb
try :
print "[Debug] SQL Commit"
sqldb.commit()
except MySQLdb.Error,e:
sqldb.rollback()
print "[Error-Commit] : " + str(e)
def checkEntry(domain,domaintype):
global sqlcur
sqlstring = """SELECT dnslog_domain_id FROM dnslog_domains WHERE `dnslog_domain_name` = '%s' AND
`dnslog_domain_type` = '%s'""" % (domain,domaintype)
dbExecute(sqlstring)
row = sqlcur.fetchone()
if row :
return row[0]
else :
sqlvalues = prepareInsertDomain(domain,domaintype)
sqlinsert = """INSERT INTO dnslog_domains VALUES ('','%s','%s','%s','%s','%s','%s','%s','%s')
""" % (sqlvalues[0],sqlvalues[1],sqlvalues[2],sqlvalues[3],sqlvalues[4],sqlvalues[5],sqlvalues[6],sqlvalues[7])
dbExecute(sqlinsert)
return sqlcur.lastrowid
def bestaadRequest(datum,tijd,requester,domainId):
global sqlcur
sqlstring = """SELECT dnslog_request_id, dnslog_request_count FROM dnslog_requests WHERE `dnslog_domain_id` = '%s' AND
`dnslog_request_requester` = '%s' AND `dnslog_request_date` = '%s' AND `dnslog_request_time` = '%s'
""" % (domainId,requester,datum,tijd)
dbExecute(sqlstring)
row = sqlcur.fetchone()
if row :
teller = int(row[1]) + 1
sqlinsert = """UPDATE `dnslog_requests` SET `dnslog_request_count` = '%s' WHERE `dnslog_request_id` = '%s' """ % (teller, row[0])
dbExecute(sqlinsert)
return row[0]
else :
sqlinsert = """INSERT INTO dnslog_requests VALUES ('','%s','%s','%s','%s','%s') """ % (domainId,requester,datum,tijd,"1")
dbExecute(sqlinsert)
return sqlcur.lastrowid
# Main starting function
if __name__ == '__main__':
dbConnect()
leesBestand(dnslog)
dbCommit()
dbClose()
数据库布局
mysql> describe dnslog_requests;
+--------------------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------------+-------------+------+-----+---------+----------------+
| dnslog_request_id | int(11) | NO | PRI | NULL | auto_increment |
| dnslog_domain_id | int(11) | YES | | NULL | |
| dnslog_request_requester | varchar(15) | NO | | NULL | |
| dnslog_request_date | date | NO | | NULL | |
| dnslog_request_time | time | NO | | NULL | |
| dnslog_request_count | int(11) | NO | | NULL | |
+--------------------------+-------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
mysql> describe dnslog_domains;
+---------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+--------------+------+-----+---------+----------------+
| dnslog_domain_id | int(11) | NO | PRI | NULL | auto_increment |
| dnslog_domain_name | varchar(250) | NO | | NULL | |
| dnslog_domain_type | varchar(15) | NO | | NULL | |
| dnslog_domain_part1 | varchar(100) | NO | | NULL | |
| dnslog_domain_part2 | varchar(100) | NO | | NULL | |
| dnslog_domain_part3 | varchar(100) | NO | | NULL | |
| dnslog_domain_part4 | varchar(100) | NO | | NULL | |
| dnslog_domain_part5 | varchar(100) | NO | | NULL | |
| dnslog_domain_part6 | varchar(100) | NO | | NULL | |
+---------------------+--------------+------+-----+---------+----------------+
【问题讨论】:
-
是否可以更频繁地清除 DNS 日志文件?目前多久清除一次日志文件
-
我打算每天做一次,当每个人都走了,因为我在移动 dnslog 文件之前很好地停止了 dns 服务,然后再次重新启动服务。
-
所以一天就增长到大约 70k 行?
-
是的,那是正确的 :) 也许是高峰日,到目前为止我可以告诉其他人大约 50/60k。
-
逐行插入或更新可能会很昂贵。相反,您可以使用批量插入。也许您可以使用暂存表来加载原始数据并运行查询来转换数据以加载实际表。
标签: python mysql performance dns