PHP и SQL: код действительно медленный

#php #mysql #sql

#php #mysql #sql

Вопрос:

 $unique = array();
$sql = "SELECT ID, TitleName, ArtistDisplayName, Mix FROM values_to_insert as A
        WHERE A.ID = ";

//Get a single row from our data that needs to be inserted...
while($result = $conn->query(($sql. $count)))
{

    //Get the $data of the single row query for inserting.
    $data = mysqli_fetch_row($result);
    $count  ;

    //SQL to get a match of the single row of $data we just fetched...
    $get_match = "SELECT TitleName_ti, Artist_ti, RemixName_ti from titles as B
                    Where B.TitleName_ti = '$data[1]'
                    and B.Artist_ti = '$data[2]'
                    and B.RemixName_ti = '$data[3]' 
                    LIMIT 1";

    //If this query returns a match, then push this data to our $unique value array.
    if(!$result = $conn->query($get_match))
    {
        //If this data has been pushed already, (since our data includes repeats), then don't 
        //put a repeat of the data into our unique array. Else, push the data.
        if(!in_array($unique, $data))
        {
            echo 'Pushed to array: ' . $data[0] . "---" . $data[1] . "</br>";
            array_push($unique, $data);
        }
        else
            echo'Nothing pushed... </br>';
    }
}
  

Это заняло более 5 минут, и ничего даже не было выведено на экран. Мне любопытно, что отнимает так много времени и, возможно, альтернативный метод или функция для того, что отнимает все это время. Я думаю, что несколько указателей в правильном направлении было бы здорово.

Этот код в основном получает все строки, по одной за раз, таблицы ‘A’. Проверяет, есть ли совпадение в таблице ‘B’, и если есть, то мне не нужны эти $ data, но если их нет, я затем проверяю, являются ли сами данные повторяющимися, потому что в моей таблице ‘A’ есть некоторые повторяющиеся значения.

В таблице A 60 000 строк, в таблице B 200 000 строк

Комментарии:

1. Если у вас нет никаких индексов в таблице B, то вы ищете 12000000000 строк.

2. Что ж… вы вкладываете два запроса, и по вашим значениям вы выполняете 60000 x 200000 запросов… Конечно, это будет медленно. Вы должны объединить оба запроса в один. Ну, вы должны. JOIN — ваш друг.

3. В качестве отступления обратите внимание, что ОГРАНИЧЕНИЕ без ORDER BY — довольно бессмысленная концепция.

4. Кажется, что вы повторно выполняете первый запрос, получаете первую строку и затем выполняете запрос снова. Вам нужно выполнить запрос один раз, а затем для цикла получить каждую строку. Вы меняете значение, но какие значения a.id вы ожидаете совпадения на? Вы просто выполняете запрос для всего, начиная с (вероятно) 1.

5. Объединения — это концепция, с которой вам необходимо ознакомиться самостоятельно. Никогда не выполняйте запрос внутри цикла (за исключением случаев, когда используются связанные параметры)

Ответ №1:

Запросы внутри запросов редко бывают хорошей идеей

Но, похоже, в вашем скрипте есть несколько проблем. Возможно, было бы проще просто выполнить все в SQL и каждый раз отправлять результаты в массив. SQL может удалять дубликаты:-

 <?php 

$unique = array();
$sql = "SELECT DISTINCT A.ID, 
                A.TitleName, 
                A.ArtistDisplayName, 
                A.Mix 
        FROM values_to_insert as A
        LEFT OUTER JOIN titles as B
        ON B.TitleName_ti = A.ID
        and B.Artist_ti = A.TitleName
        and B.RemixName_ti = A.ArtistDisplayName
        WHERE B.TitleName_ti IS NULL
        ORDER BY a.ID";

if($result = $conn->query(($sql)))
{
    //Get the $data of the single row query for inserting.
    while($data = mysqli_fetch_row($result))
    {
        array_push($unique, $data);
    }
}
  

Что касается вашего исходного запроса.

У вас есть счетчик (я предполагаю, что он инициализируется значением 0, но если символ, то это приведет к странным вещам), и получите записи с этим значением. Если первый идентификатор был 1,000,000,000, то вы выполнили 1b запросов, прежде чем нашли запись для обработки. Вы можете просто получить все строки в порядке идентификаторов в любом случае, удалив предложение WHERE и упорядочив по идентификатору.

Затем вы просто получаете единственную запись из 2-го запроса, где детали совпадают, но обрабатываете их только в том случае, если запись не найдена. Вы не используете ни одно из возвращаемых значений. Вы можете сделать это, выполнив LEFT OUTER JOIN для получения совпадений и проверив, что в предложении WHERE совпадений не было.

РЕДАКТИРОВАТЬ — как вы указали, поля, которые вы, по-видимому, используете для сопоставления записей, логически не совпадают. Я использовал их так же, как и вы, но я ожидаю, что вы действительно хотите сопоставить B.TitleName_ti с A.TitleName, B.Artist_ti с A.ArtistDisplayName и B.RemixName_ti с A.Mix

Комментарии:

1. Ваше B.TitleName_ti = A.ID не соответствуют?

2. TitleName и ID никогда не будут равны.

3. @DJSweetness — возможно, это очень верно, но это способ, с помощью которого исходные запросы posters соответствуют действительности.