Оптимизация во время выполнения C # -> MySQL - PullRequest
0 голосов
/ 20 февраля 2019

Я пытаюсь записать данные в базу данных MySql через c #.Проблема в том, что все столбцы вместе должны быть уникальными, но они слишком длинные для ключа.Чтобы проверить наличие дубликатов, в настоящее время у меня есть запрос на выборку, чтобы проверить, существует ли запись и не будет ли она добавлена ​​с помощью запроса на вставку.Теперь скрипт выполняется один раз в день и проверяет несколько миллионов записей, если они уже есть, а если нет, то они будут добавлены.

пример: при 2 миллионах это будет 2 миллиона запросов на выборку более чем на миллион строк и сновавставьте запросы для всех, кто не является дубликатом.

Есть ли лучший способ проверить наличие дубликатов?Как я сказал уникальный, только все столбцы вместе.Выбор должен быть длиннее и длиннее, чем больше строк ...

foreach (var item in list)
{
    string query = "SELECT id FROM dirs WHERE Directory = \"" + item.dir + "\" AND IdentityReference = \"" + item.IdentityReference + "\" AND AccessControlType = \"" + item.AccessControlType + "\" AND FileSystemRights = \"" + item.FileSystemRights + "\" AND IsInherited = " + item.IsInherited.ToString();

    MySqlCommand commanDatabase = new MySqlCommand(query, databaseConnection);
    MySqlDataReader dataReader = commanDatabase.ExecuteReader();

    bool duplicate = false;
    while (dataReader.Read())
    {
        duplicate = true;
        break;
    }

    dataReader.Close();

    if (!duplicate)
    {
        query = "INSERT INTO dirs (Directory, IdentityReference, AccessControlType, FileSystemRights, IsInherited) VALUES ";
        query += "(\"" + item.dir + "\", \"" + item.IdentityReference + "\", \"" + item.AccessControlType + "\", \"" + item.FileSystemRights + "\", " + item.IsInherited.ToString() + ")";

        commanDatabase = new MySqlCommand(query, databaseConnection);
        commanDatabase.CommandTimeout = 60;
        commanDatabase.ExecuteNonQuery();
    }
}

Ответы [ 2 ]

0 голосов
/ 20 февраля 2019

вы можете использовать виртуальный столбец, который автоматически генерирует контрольную сумму MD5 из вашего ROW, и хранилище находится в новом поле с уникальным индексом.

Примечание. Существует небольшая разница в синтаксисе между MySQL и MariaDB.

образец

Ваш стол

CREATE TABLE `mytable` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `Directory` varchar(128) DEFAULT NULL,
  `IdentityReference` varchar(128) DEFAULT NULL,
  `AccessControlType` varchar(128) DEFAULT NULL,
  `FileSystemRights` varchar(128) DEFAULT NULL,
  `IsInherited` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

добавить2 записи

MariaDB [chksum]> INSERT INTO `mytable` (`id`, `Directory`, `IdentityReference`, `AccessControlType`, `FileSystemRights`, `IsInherited`)
    ->     VALUES
    ->         (1, '/usr/local', 'yes', 'rwxrwxrwx', 'NO', 7),
    ->         (2, '/etc/var/log', 'yes', 'xxxxx', 'YES', 99);
Query OK, 2 rows affected (0.003 sec)
Records: 2  Duplicates: 0  Warnings: 0

MariaDB [chksum]> select * from mytable;
+----+--------------+-------------------+-------------------+------------------+-------------+
| id | Directory    | IdentityReference | AccessControlType | FileSystemRights | IsInherited |
+----+--------------+-------------------+-------------------+------------------+-------------+
|  1 | /usr/local   | yes               | rwxrwxrwx         | NO               |           7 |
|  2 | /etc/var/log | yes               | xxxxx             | YES              |          99 |
+----+--------------+-------------------+-------------------+------------------+-------------+
2 rows in set (0.000 sec)

MariaDB [chksum]>

Измените таблицу, добавьте новое поле

MariaDB [chksum]> ALTER TABLE `mytable`
    -> ADD COLUMN
    -> `chksum` VARCHAR(32) AS (
    ->     MD5(
    ->         CONCAT(    `DIRECTORY`,'-',
    ->                 `IdentityReference`,'-',
    ->                 `AccessControlType`,'-',
    ->                 `FileSystemRights` ,'-',
    ->                 `IsInherited`
    ->             )
    ->         )
    -> )  PERSISTENT ,
    -> ADD  UNIQUE KEY `idx_chksum` (`chksum`);
Query OK, 2 rows affected (0.029 sec)
Records: 2  Duplicates: 0  Warnings: 0

просмотреть содержимое с новым полем

MariaDB [chksum]> select * from mytable;
+----+--------------+-------------------+-------------------+------------------+-------------+----------------------------------+
| id | Directory    | IdentityReference | AccessControlType | FileSystemRights | IsInherited | chksum                           |
+----+--------------+-------------------+-------------------+------------------+-------------+----------------------------------+
|  1 | /usr/local   | yes               | rwxrwxrwx         | NO               |           7 | 5b812d391703099e6fea16f8a590891e |
|  2 | /etc/var/log | yes               | xxxxx             | YES              |          99 | 99a5e08acb58b23618bdb9f40737e5cf |
+----+--------------+-------------------+-------------------+------------------+-------------+----------------------------------+
2 rows in set (0.002 sec)

MariaDB [chksum]>

вставить строку без дублирующего ключа

MariaDB [chksum]> INSERT INTO `mytable` (`id`, `Directory`, `IdentityReference`, `AccessControlType`, `FileSystemRights`, `IsInherited`)
    -> VALUES
    ->     (NULL, '/usr/local/XXX', 'yes', 'rwxrwxrwx', 'NO', 7);
Query OK, 1 row affected (0.002 sec)

MariaDB [chksum]> INSERT INTO `mytable` (`id`, `Directory`, `IdentityReference`, `AccessControlType`, `FileSystemRights`, `IsInherited`)
    -> VALUES
    ->     (NULL, '/usr/local', 'yes', 'rwxrwxrwx', 'NO', 7);
ERROR 1062 (23000): Duplicate entry '5b812d391703099e6fea16f8a590891e' for key 'idx_chksum'
MariaDB [chksum]>
0 голосов
/ 20 февраля 2019

[предложения]

  1. Используйте параметры.
  2. Почему бы не использовать Insert if not exists?(в основном объединяя ваш первый и второй запросы вместе)
  3. Измените свой дизайн БД: Вы можете добавить в свою таблицу новое поле, которое вычисляет значения хеш-функции для желаемых столбцов.Который затем используется для проверки уникальности.

Что-то вроде:

Select Sha1(concat_ws('',Directory, IdentityReference, AccessControlType, FileSystemRights, IsInherited)) As HashValue

Который затем можно легко использовать для идентификации уникальных значений.

`` ИЛИ Объединение запроса вставки и проверки дубликатов может выглядеть следующим образом.

INSERT INTO dirs (Directory, IdentityReference, AccessControlType, FileSystemRights, IsInherited)
SELECT
    @Directory, @IdentityReference, @AccessControlType, @FileSystemRights, @IsInherited
FROM Dual
WHERE
    1 not in (SELECT 1 From dirs WHERE Directory = @Directory, IdentityReference = @IdentityReference, AccessControlType=@AccessControlType, FileSystemRights = @FileSystemRights );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...