Запрос к базе данных при перезаписи - PullRequest
0 голосов
/ 02 июня 2018

У меня есть PHP-скрипт, который запускается каждые 5 минут и получает данные из API, а затем записывает их в таблицу MySQL.Пользователи (более 300) моего сайта могут запрашивать эти данные через таблицы данных, а другие страницы представляют некоторые из этих данных.PHP-скрипт получает данные API, затем

foreach($array as $row)
{
    $query .= "INSERT INTO table_name 
    (
        col_name1, 
        col_name2, 
        col_name3, 
        col_name4, 
        col_name5
    ) 
    VALUES
    (
        '".$row["value1"]."', 
        '".$row["value2"]."', 
        '".$row["value3"]."', 
        '".$row["value4"]."', 
        '".$row["value5"]."'
    );";
}

mysqli_query($connect, "DELETE FROM table_name");

mysqli_multi_query($connect, $query);

DELETE, а затем вставляет в эту пустую таблицу при каждом запуске скрипта.Таблица имеет 1000 строк, и это будет расти со временем.Я получаю сообщения о том, что таблица данных иногда пуста, и им придется обновляться несколько раз, прежде чем что-либо появится.

Есть ли лучший способ структурирования БД, таблиц и / или запросов.

1 Ответ

0 голосов
/ 02 июня 2018

Запуск отдельных операторов вставки для каждой строки будет мучительно медленным.

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

INSERT INTO t (a,b,c) VALUES (?,?,?) ,(?,?,?) ,(?,?,?) ,(?,?,?)

Один потенциальный недостаток - если одна строка не может быть вставлена ​​из-за ошибки, весь оператор откатывается, и ни одна из строк не вставляется.

Максимальная длина оператора SQL ограничена max_allowed_packet.Нет необходимости вставлять все строки в один оператор.Вставка 10 строк во всплывающем окне значительно сократит количество выполнений операторов.

Предполагается, что в таблице используется механизм хранения InnoDB ...

Если мы отключим автоматическую фиксацию и запустим DELETE оператор и операторы INSERT в контексте одной транзакции , тогда таблица не будет выглядеть "пустой" для других сеансов.Другие сеансы будут продолжать видеть содержимое таблицы, как это было до DELETE ... до тех пор, пока COMMIT не будет завершено.


Шаблон кода кажется уязвимым для SQL-инъекций.(И особенно открыты для многих мерзостей, используя несколько запросов.

Лучшая практика для смягчения SQL-инъекций - это использование подготовленных операторов с заполнителями связывания.

https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet


EDIT

В качестве альтернативного подхода, если таблица имеет первичный ключ или уникальный ключ, рассмотрим

загрузку временной таблицы (не целевой таблицы).

Затем запустите операторы, чтобы применить изменения для синхронизации целевой таблицы с временной таблицей. Мы будем ссылаться на временную таблицу по имени источника.

- обновить существующие строки

 UPDATE target t 
   JOIN source s
     ON s.id = t.id
    SET t.col = s.col 
      , t.foo = s.foo
      , t.bar = s.bar

- вставлять новые строки

INSERT INTO target
SELECT s.*
  FROM ( SELECT r.*
           FROM source r
             -- anti-join 
           LEFT
           JOIN target q
             ON q.id = r.id 
          WHERE q.id IS NULL
        ) s

- удалять удаленные строки

 DELETE t.*
   FROM target t
     -- anti-join
   LEFT
   JOIN source s
     ON s.id = t.id
  WHERE s.id IS NULL 

Это позволяет избежать необходимости «очищать» целевую таблицу, поэтому одновременноОператоры SELECT будут по-прежнему возвращать строки, пока целевая таблица «синхронизируется».

Операции DML UPDATE / INSERT / DELETE для целевой таблицы могут выполняться в контексте одной транзакции.

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