对于大数据量的情况,如您所述的300MB数据,直接一次性加载所有数据到内存中可能会导致性能问题或内存溢出。为了有效处理这种情况,您可以采用分批次读取数据的策略。这种策略可以通过使用数据库的分页功能来实现,通常使用 LIMIT
和 OFFSET
语句或者是逐步增加的条件来逐步读取数据。
分批读取策略
- 使用 LIMIT 和 OFFSET:这是最直接的分页技术,但对于非常大的偏移量可能效率低下。
- 使用条件和索引:基于时间戳的条件查询,每次查询后续的一批数据,这通常更高效,尤其是当时间戳字段有索引时。
示例代码
以下是一个示例,展示如何使用时间戳进行分批读取和发送数据:
import threading
import socket
import sqlite3
import time
# 数据库配置
DATABASE = 'your_database.db'
BATCH_SIZE = 1000 # 每批次读取1000条数据
# 网络配置
HOST = 'localhost'
PORT = 12345
def read_and_send_data():
last_timestamp = 0 # 假设时间戳从0开始
more_data = True
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect((HOST, PORT))
while more_data:
conn = sqlite3.connect(DATABASE)
cursor = conn.cursor()
# 查询比上次读取的最后一个时间戳更大的下一批数据
cursor.execute("SELECT timestamp, data FROM your_table WHERE timestamp > ? ORDER BY timestamp ASC LIMIT ?", (last_timestamp, BATCH_SIZE))
rows = cursor.fetchall()
cursor.close()
conn.close()
if not rows:
more_data = False # 如果没有数据,结束循环
continue
for timestamp, datum in rows:
sock.sendall(datum.encode()) # 发送数据
time.sleep(1/2500) # 控制发送速率为每秒2500个数据
last_timestamp = timestamp # 更新最后处理的时间戳
def handle_client(connection):
try:
while True:
data = connection.recv(1024) # 读取数据
if not data:
break
process_data(data)
finally:
connection.close()
def process_data(data):
print("Received data:", data)
def server():
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.bind((HOST, PORT))
sock.listen(5)
while True:
client_socket, addr = sock.accept()
client_thread = threading.Thread(target=handle_client, args=(client_socket,))
client_thread.start()
if __name__ == "__main__":
server_thread = threading.Thread(target=server)
server_thread.start()
send_thread = threading.Thread(target=read_and_send_data)
send_thread.start()
server_thread.join()
send_thread.join()
说明
- 分批读取:通过
WHERE timestamp > last_timestamp
来确保每次只读取上次读取之后的数据。 - 索引优化:确保数据库中的
timestamp
字段是索引的,这可以显著提高查询性能。 - 发送控制:通过
time.sleep(1/2500)
控制数据发送速率。
这种方法可以有效地处理大量数据的分批读取和发送,避免了一次性加载大量数据带来的内存压力。