Class Database {
private SQLiteConnection myDB;
private SQLiteCommand cmd;
public Database {
//create database file, create connection info, etc)
String sql = "CREATE TABLE IF NOT EXISTS 'myTable' (id INTEGER PRIMARY KEY, user TEXT, currency INTEGER DEFAULT 0)";
using (cmd = new SQLiteCommand(sql, myDB))
{
cmd.ExecuteNonQuery();
}
}
public void newUser(String user) {
String sql = "INSERT INTO myTable (user) VALUES '" + user + "'";
cmd = new SQLiteCommand(myDB, sql);
cmd.ExecuteNonQuery();
}
private bool userExists(String user) {
String sql = "SELECT * FROM '" + channel + "';";
using (cmd = new SQLiteCommand(sql, myDB))
{
using (SQLiteDataReader r = cmd.ExecuteReader())
{
while (r.Read())
{
if (r["user"].ToString().Equals(user, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
}
}
return false;
}
public void AddCurrency(String user, int amount) {
if (!userExists(user)) {
newUser(user);
}
using (cmd = myDB.CreateCommand())
{
cmd.CommandText = "UPDATE '" + channel + "' SET currency = currency + @amount WHERE user = @user";
cmd.Parameters.Add(new SQLiteParameter("@amount", amount));
cmd.Parameters.Add(new SQLiteParameter("@user", user));
cmd.ExecuteNonQuery();
}
}
}
Class Stuff {
public void Main(String[] args) {
Database db = new Database();
//blah blah blah
//blah blah blah
//blah blah blah
//Do stuff and generate an array called users that is alist of all the users in the channel
//Here's what I currently do
foreach (String person in users) {
db.AddCurrency(person, 1);
}
}
}
正如您可能看到的那样,问题在于,对于大型用户列表(例如,1000个用户),我可能会进行多达3000次查询。它在小规模上工作正常,但是当用户列表变得太大时,它真的开始陷入困境(特别是写查询)。所以我想把它改成像db.AddCurrency(users,1);发送整个数组,但我有其他问题。例如,在SQLite中似乎没有“Upsert”(如果不存在则插入,否则更新)类型命令。关于如何缩短大型用户列表上的运行时间的任何想法?
作为参考,这是http://twitch.tv的聊天机器人的一部分。它似乎适用于我所有的当前用户,即使他们有多达100或200个并发查看器。但有一天,出于好奇,我在一个拥有超过4k观众的流中运行它,并且花了2分钟+来完成所有数据库更新。这不是一个问题现在,但我觉得这是我想要解决的问题,如果可能的话。
**注意:我正在使用System.Data.SQLite库。
答案 0 :(得分:0)
在您的用户和货币列上创建索引。
CREATE INDEX 'userName' ON 'tablename' ('user' ASC);
CREATE INDEX 'currencyAMT' on 'tablename' ('currency' ASC);
在create table命令之后,将这些命令作为单独的命令传递到数据库构造函数中。这应该在列上创建索引。 (我的系统ATM上没有SQLLite,所以我没有能力测试)
另外,在你的userExists方法中,为你的SQL添加一个where子句,这样你就可以得到一个记录集,其中user =你传入的用户。
"SELECT * FROM '" + channel + "' WHERE user = '" & user & "';";
如果您没有收到任何记录,则该用户不存在。如果您确实收到了记录,则该用户确实存在。
这会将你的O(n)搜索减少到更像O(1)的东西。