Использование SQLite для миллиардов записей - PullRequest
1 голос
/ 04 апреля 2019

В моем приложении WPF я вставляю данные клиента в базу данных SQLite. У меня есть 2 таблицы (Zip и Customer). Данные могут расти до миллиардов. Мне нужны быстрые вставки и извлечения из БД.

Я использую SQLite, так как приложение будет использоваться только в одной системе. Согласно моим исследованиям, SQLite может обрабатывать ТБ данных, поэтому я хочу знать, что с ним не так?

Ранее я использовал MySQL и EF, но вставка и получение были очень медленными.

Это две таблицы. При получении информации о клиенте из ZipCode будет добавлена ​​запись.

CREATE TABLE ZIPCODE(
                    Zip NUMERIC PRIMARY KEY ,
                    City VARCHAR,
                    County VARCHAR,
                    State VARCHAR
                );
CREATE TABLE CUSTOMER(
                Phone NUMERIC PRIMARY KEY,
                FirstName VARCHAR,
                LastName VARCHAR,
                Address VARCHAR,
                Zip NUMERIC,
                Status CHAR(5),
                Category CHAR(10),
                Options CHAR(5),
                Email VARCHAR,
                Seconds NUMERIC,
                FOREIGN KEY(Zip) REFERENCES ZIPCODE(Zip)
            );

Ниже приведена функция C #, которую я использую для вставки данных.

public int AddCustomersToDB(List<Customer> customers)
        {
            int invalidCount = 0;
            try
            {
                _dbConnection.Open();
                using (var cmd = new SQLiteCommand(_dbConnection))
                {
                    using (var transaction = _dbConnection.BeginTransaction())
                    {
                        foreach (Customer c in customers)
                        {
                            string values = String.Format("\"{0}\",\"{1}\",\"{2}\",\"{3}\",\"{4}\",\"{5}\",\"{6}\",\"{7}\",\"{8}\",\"{9}\"", c.Phone, c.FirstName, c.LastName, c.Address, c.Zip, c.Status, c.Category, c.Options, c.Email, c.Seconds);
                            cmd.CommandText = String.Format(@"INSERT INTO CUSTOMER(Phone,FirstName,LastName,Address,Zip,Status,Campaign,Options,Email,Seconds) VALUES ({0});", values);
                            try
                            {
                                cmd.ExecuteNonQuery();
                            }
                            catch (SQLiteException e)
                            {
                                invalidCount++;
                                continue;
                            }
                        }
                        transaction.Commit();
                    }
                }
                return invalidCount;
            }
            catch (SQLiteException e)
            {
                throw new Exception("SQLiteException:" + e.Message);
            }
            finally { _dbConnection.Close(); }
        }

Нужны некоторые предложения относительно этого подхода, у меня есть код на GitHub, поэтому, если кто-то захочет посмотреть полный код, я тоже могу поделиться этим.

1 Ответ

1 голос
/ 04 апреля 2019

Я бы изменил несколько вещей. Я бы использовал параметры команды sql, так как это предотвратит атаки с использованием SQL-инъекций и очистит ваш код. Блок try / catch / finally делает ваш код более подверженным ошибкам, так как вы должны вручную удалить соединение. Оборачивание вашего кода в с использованием блока гарантирует, что вызов Dispose будет вызван, даже если в блоке using происходит исключение.

Что касается ваших вопросов по SQLite - максимальный размер базы данных для базы данных SQLite составляет приблизительно 140 терабайт. Таким образом, он может обрабатывать много данных, , но вы хотите использовать базу данных SQLite такого размера ?

Я использовал SQLite в нескольких проектах, но никогда для больших наборов данных. Недостатком его использования для больших наборов данных является то, что он хранит всю базу данных в одном файле на диске, и многие файловые системы ограничивают максимальный размер файлов до значений, меньших ограничений SQLite.

Я бы ознакомился со следующими правилами общего использования: Подходящее использование для SQLite .

Пример кода, показывающего использование параметра и использование блока:

        var customers = new List<Customer>(); // get your customers

        using (var conn = new SQLiteConnection("your connection string"))
        {
            await conn.OpenAsync();

            using (var cmd = new SQLiteCommand(conn))
            {
                cmd.CommandText = cmd.CommandText = "INSERT INTO CUSTOMER (Phone, FirstName) VALUES(@param1, @param2)";
                cmd.CommandType = CommandType.Text;

                using (var trans = conn.BeginTransaction())
                {
                    foreach (var c in customers)
                    {
                        cmd.Parameters.AddWithValue("@param1", c.Phone);
                        cmd.Parameters.AddWithValue("@param2", c.FirstName);

                        await cmd.ExecuteNonQueryAsync();
                    }
                }
            }
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...