Как улучшить скорость этих запросов PHP MySQLi без индексации? - PullRequest
0 голосов
/ 27 марта 2019

Давайте начнем с того, что я не могу использовать INDEXING, так как мне нужны INSERT, DELETE и UPDATE, чтобы эта таблица была супербыстрой, какой они есть.

У меня есть страница, которая отображает сводку единиц заказа, собранных в таблице базы данных. Чтобы заполнить таблицу, создается номер заказа, а затем отдельные таблицы, связанные с этим заказом, сканируются в таблицу, чтобы узнать, какие единицы связаны с каждым заказом.

Для целей этого примера таблица имеет следующие столбцы.

id, UID, заказ, отправитель, получатель, дата и время

Количество отдельных единиц может быть в тысячах на заказ, а вся таблица увеличивается до сотен тысяч единиц.

На странице сводки отображается количество единиц в заказе, а также номер первой и последней единицы для каждого заказа. Я ограничиваю количество отображаемых заказов последними 30 номерами заказов.

Например:

Заказ 10 состоит из 200 единиц. первый UID 1510 последний UID 1756

Заказ 11 состоит из 300 единиц. первый UID 1922 последний UID 2831

..........

..........

В настоящее время время ответа на запрос составляет около 3 секунд, поскольку код выполняет следующее:

  1. Поиск последних 30 заказов по идентификатору и сортировка по номеру заказа

  2. При просмотре каждого номера заказа в массиве

- Подсчитать количество строк в базе данных с таким номером заказа

- выберите первый UID из всех строк как первый

- Выберите последний UID из всех строк как последний

  1. Показать результат

Я определил, что большую часть времени занимает подсчет количества единиц в каждом порядке ~ 1,8 секунды, а затем определение первого и последнего чисел в каждом порядке ~ 1 секунда.

Мне действительно интересно, есть ли способ ускорить эти запросы без INDEXING. Вот код с запросами.

Первый запрос выбирает последние 30 обработанных заказов, выбранных по идентификатору и сгруппированных по номеру заказа. Это дает последние 30 уникальных номеров заказа.

$result = mysqli_query($con, "SELECT order, ANY_VALUE(receiver) AS receiver, ANY_VALUE(originator) AS originator, ANY_VALUE(id) AS id 
FROM scandb
GROUP BY order 
ORDER BY id 
DESC LIMIT 30");

При получении последних 30 номеров заказов подсчитайте количество единиц, а также первый и последний UID для каждого заказа.


while($row=mysqli_fetch_array($result)){

    $count = mysqli_fetch_array(mysqli_query($con, "SELECT order, COUNT(*) as count FROM scandb WHERE order ='".$row['order']."' "));

    $firstLast = mysqli_fetch_array(mysqli_query($con, "SELECT (SELECT UID FROM scandb WHERE orderNumber ='".$row['order']."' ORDER BY UID LIMIT 1) as 'first', (SELECT UID FROM barcode WHERE order ='".$row['order']."' ORDER BY UID DESC LIMIT 1) as 'last'"));

echo "<td align= center>".$count['count']."</td>";
echo "<td align= center>".$firstLast['first']."</td>";
echo "<td align= center>".$firstLast['last']."</td>";

}

При 100 тыс. Строк в базе данных весь этот запрос занимает около 3 секунд. Большую часть времени составляют запросы $ count и $ firstlast. Я хотел бы знать, есть ли более эффективный способ получить эти же данные за более короткое время без индексации таблицы. Любые специальные уловки, которые кто-либо имеет, будут с благодарностью.

1 Ответ

1 голос
/ 27 марта 2019

Создайте базу данных с осторожностью

Этот первый совет может показаться очевидным, но дело в том, что большинство проблем с базами данных происходит из-за плохо спроектированной структуры таблиц. Например, я видел людей, хранящих информацию, такую ​​как информация о клиенте и информацию об оплате, в одном столбце базы данных. И для системы баз данных, и для разработчиков, которым придется над ней работать, это не очень хорошая вещь. При создании базы данных всегда размещайте информацию в различных таблицах, используйте четкие стандарты именования и используйте первичные ключи.

Знайте, что вы должны оптимизировать

Если вы хотите оптимизировать конкретный запрос, крайне полезно иметь возможность подробно изучить результат запроса. Используя оператор EXPLAIN, вы получите много полезной информации о результате, полученном по конкретному запросу, как показано в следующем примере:

EXPLAIN SELECT * FROM ref_table,other_table WHERE ref_table.key_column=other_table.column;

Не выбирайте то, что вам не нужно

Очень распространенный способ получения нужных данных - использовать символ *, который будет получать все поля из нужной таблицы:

SELECT * FROM wp_posts;

Вместо этого вам обязательно нужно выбрать только нужные поля, как показано в примере ниже. На очень маленьком сайте, скажем, с одним посетителем в минуту, это не будет иметь значения. Но на таком сайте, как Cats Who Code, это экономит много работы для базы данных.

SELECT title, excerpt, author FROM wp_posts;

Избегать запросов в циклах

При использовании SQL вместе с языком программирования, таким как PHP, может возникнуть соблазн использовать SQL-запросы внутри цикла. Но это все равно что забивать вашу базу данных запросами. Этот пример иллюстрирует всю проблему «запросов в циклах»:

foreach ($display_order as $id => $ordinal) {
    $sql = "UPDATE categories SET display_order = $ordinal WHERE id = $id";
    mysql_query($sql);
}
Here is what you should do instead:
UPDATE categories
    SET display_order = CASE id
        WHEN 1 THEN 3
        WHEN 2 THEN 4
        WHEN 3 THEN 5
    END
WHERE id IN (1,2,3)

Использовать объединение вместо подзапросов

Как программист, подзапросы - это то, что вы можете использовать и злоупотреблять ими. Подзапросы, как показано ниже, могут быть очень полезны:

SELECT a.id,
    (SELECT MAX(created)
    FROM posts
    WHERE author_id = a.id)
AS latest_post FROM authors a

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

SELECT a.id, MAX(p.created) AS latest_post
FROM authors a
INNER JOIN posts p
    ON (a.id = p.author_id)
GROUP BY a.id

Источник: http://20bits.com/articles/10-tips-for-optimizing-mysql-queries-that-dont-suck/

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