Tôi đang sử dụng datatables để hiển thị dữ liệu từ nhiều bảng mySQL (7 trong số chúng thực sự). Hiện tại không có nhiều dữ liệu, nhưng tôi thấy "Hiển thị 1 đến 7 trong số 7 mục (được lọc từ 642,660,480 tổng số mục nhập)." và mất 20 giây để chỉ hiển thị 7 mục nhập. Khi tôi thực sự bắt đầu thêm nhiều nội dung vào cơ sở dữ liệu, tôi chắc chắn điều này sẽ không thể sử dụng được.DataTables: Tăng tốc xử lý phía máy chủ với nhiều bảng, nhóm và nội dung html?
Tôi chắc chắn rằng có những cách tốt hơn để hoàn thành những gì tôi đang cố gắng làm, nhưng đây là cách duy nhất tôi có thể làm cho nó hoạt động.
Đây là kịch bản phía máy chủ của tôi:
$q1 = "'";
$q2 = '"';
$order_id = "CONCAT(".$q2."<input type='hidden' id='order_id' value='".$q2.", o.id, ".$q2."'><a href='order_details.php?id=".$q2.", o.id, ".$q2."'><img src='https://pas.greysignal.com/img/search.png' border='0'></a> ".$q2.", o.id)";
$patient_name = "CONCAT(".$q2."<input type='hidden' id='patient_name' value='".$q2.", p.first_name, ' ', p.last_name, ".$q2."'><input type='hidden' id='patient_id' value='".$q2.", p.id, ".$q2."'><input type='hidden' id='patient_ssn' value='".$q2.", p.ssn, ".$q2."'><a href='patient_details.php?id=".$q2.", p.id, ".$q2."'><img src='https://pas.greysignal.com/img/search.png' border='0'></a> ".$q2.", p.first_name, ' ', p.last_name)";
$doc_name = "CONCAT(".$q2."<input type='hidden' id='doctor_name' value='".$q2.", d.first_name, ' ', d.last_name, ".$q2."'><input type='hidden' id='doctor_id' value='".$q2.", d.id, ".$q2."'><a href='doctor_details.php?id=".$q2.", d.id, ".$q2."'><img src='https://pas.greysignal.com/img/search.png' border='0'></a> ".$q2.", d.first_name, ' ', d.last_name)";
$order_date = "FROM_UNIXTIME(o.created_timestamp, '%m/%e/%Y')";
$tests = "GROUP_CONCAT(t.name SEPARATOR ', ')";
$aColumns = array($order_id, $order_date, $doc_name, $patient_name, $tests, 'o.status');
/* Indexed column (used for fast and accurate table cardinality) */
$sIndexColumn = "o.id";
/* DB table to use */
$sTable = "`orders` o, `patients` p, `doctors` d, `tests_ordered` tst, `tests` t, `users` u, `events` e";
$sWhere = "WHERE p.id = o.patient_id AND d.id = o.doctor_id AND tst.order_id = o.id AND t.id = tst.test_id AND u.username = o.assigned_username AND e.event_id = o.event_id";
$order_status = isset($_GET['status']) ? $_GET['status'] : 'all';
if($order_status == 'all'){
}else{
$sWhere .= " AND (o.status='Complete' OR o.status='$order_status')";
}
$sGroupBy = "GROUP BY o.id";
/* Database connection information */
$gaSql['user'] = DB_USER;
$gaSql['password'] = DB_PASSWORD;
$gaSql['db'] = DB_NAME;
$gaSql['server'] = DB_SERVER;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* If you just want to use the basic configuration for DataTables with PHP server-side, there is
* no need to edit below this line
*/
/*
* MySQL connection
*/
$gaSql['link'] = mysql_pconnect($gaSql['server'], $gaSql['user'], $gaSql['password'] ) or
die('Could not open connection to server');
mysql_select_db($gaSql['db'], $gaSql['link']) or
die('Could not select database '. $gaSql['db']);
/*
* Paging
*/
$sLimit = "";
if (isset($_GET['iDisplayStart']) && $_GET['iDisplayLength'] != '-1')
{
$sLimit = "LIMIT ".mysql_real_escape_string($_GET['iDisplayStart']).", ".
mysql_real_escape_string($_GET['iDisplayLength']);
}
/*
* Ordering
*/
if (isset($_GET['iSortCol_0']))
{
$sOrder = "ORDER BY ";
for ($i=0 ; $i<intval($_GET['iSortingCols']) ; $i++)
{
if ($_GET[ 'bSortable_'.intval($_GET['iSortCol_'.$i]) ] == "true")
{
$sOrder .= $aColumns[ intval($_GET['iSortCol_'.$i]) ]."
".mysql_real_escape_string($_GET['sSortDir_'.$i]) .", ";
}
}
$sOrder = substr_replace($sOrder, "", -2);
if ($sOrder == "ORDER BY")
{
$sOrder = "";
}
}
/*
* Filtering
* NOTE this does not match the built-in DataTables filtering which does it
* word by word on any field. It's possible to do here, but concerned about efficiency
* on very large tables, and MySQL's regex functionality is very limited
*/
if ($_GET['sSearch'] != "")
{
$sWhere .= " AND (";
for ($i=0 ; $i<count($aColumns) ; $i++)
{
if($i!=4){ //skip tests column
$sWhere .= $aColumns[$i]." LIKE '%".mysql_real_escape_string($_GET['sSearch'])."%' OR ";
}
}
$sWhere = substr_replace($sWhere, "", -3);
$sWhere .= ')';
}
/* Individual column filtering */
for ($i=0 ; $i<count($aColumns) ; $i++)
{
if($i!=4){ //skip tests column
if ($_GET['bSearchable_'.$i] == "true" && $_GET['sSearch_'.$i] != '')
{
if ($sWhere == "")
{
$sWhere = "WHERE ";
}
else
{
$sWhere .= " AND ";
}
$sWhere .= $aColumns[$i]." LIKE '%".mysql_real_escape_string($_GET['sSearch_'.$i])."%' ";
}
}
}
/*
* SQL queries
* Get data to display
*/
$sQuery = "
SELECT SQL_CALC_FOUND_ROWS ".str_replace(" , ", " ", implode(", ", $aColumns))."
FROM $sTable
$sWhere
$sGroupBy
$sOrder
$sLimit
";
//echo $sQuery;
//die();
$rResult = mysql_query($sQuery, $gaSql['link']) or die(mysql_error());
/* Data set length after filtering */
$sQuery = "
SELECT FOUND_ROWS()
";
$rResultFilterTotal = mysql_query($sQuery, $gaSql['link']) or die(mysql_error());
$aResultFilterTotal = mysql_fetch_array($rResultFilterTotal);
$iFilteredTotal = $aResultFilterTotal[0];
/* Total data set length */
$sQuery = "
SELECT COUNT(".$sIndexColumn.")
FROM $sTable
";
$rResultTotal = mysql_query($sQuery, $gaSql['link']) or die(mysql_error());
$aResultTotal = mysql_fetch_array($rResultTotal);
$iTotal = $aResultTotal[0];
//added to hide filtering
//$iTotal = $iFilteredTotal;
/*
* Output
*/
$output = array(
"sEcho" => intval($_GET['sEcho']),
"iTotalRecords" => $iTotal,
"iTotalDisplayRecords" => $iFilteredTotal,
"aaData" => array()
);
while ($aRow = mysql_fetch_array($rResult))
{
$row = array();
for ($i=0 ; $i<count($aColumns) ; $i++)
{
if ($aColumns[$i] != ' ')
{
/* General output */
$row[] = $aRow[$i];
}
}
$output['aaData'][] = $row;
}
echo json_encode($output);
Đây là truy vấn mà kịch bản phía máy chủ được tạo ra:
SELECT SQL_CALC_FOUND_ROWS
CONCAT("<input type='hidden' id='order_id' value='", o.id, "'><a href='order_details.php?id=", o.id, "'><img src='search.png' border='0'></a> ", o.id),
FROM_UNIXTIME(o.created_timestamp, '%m/%e/%Y'),
CONCAT("<input type='hidden' id='doctor_name' value='", d.first_name, ' ', d.last_name, "'><input type='hidden' id='doctor_id' value='", d.id, "'><a href='doctor_details.php?id=", d.id, "'><img src='search.png' border='0'></a> ", d.first_name, ' ', d.last_name),
CONCAT("<input type='hidden' id='patient_name' value='", p.first_name, ' ', p.last_name, "'><input type='hidden' id='patient_id' value='", p.id, "'><input type='hidden' id='patient_ssn' value='", p.ssn, "'><a href='patient_details.php?id=", p.id, "'><img src='search.png' border='0'></a> ", p.first_name, ' ', p.last_name), GROUP_CONCAT(t.name SEPARATOR ', '),
o.status
FROM `orders` o, `patients` p, `doctors` d, `tests_ordered` tst, `tests` t, `users` u, `events` e
WHERE p.id = o.patient_id AND d.id = o.doctor_id AND tst.order_id = o.id AND t.id = tst.test_id AND u.username = o.assigned_username AND e.event_id = o.event_id AND (o.status='Complete' OR o.status='Draft')
GROUP BY o.id
Tôi đang cố gắng để xác định những gì tôi có thể làm để tối ưu hóa này mà không vi phạm các tính năng tìm kiếm và sắp xếp của datatables. Tôi đã tạo các chỉ mục và đặt các khóa chính cho tất cả các bảng là tốt nhất như tôi biết. Có cách nào để sử dụng JOIN có thể?
Đây là kết quả của giải thích tuyên bố:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE u index NULL PRIMARY 32 NULL 5 Using index; Using temporary; Using filesort
1 SIMPLE o ALL PRIMARY,patient_id,doctor_id,event_id,assigned_use... NULL NULL NULL 6 Using where
1 SIMPLE d eq_ref PRIMARY PRIMARY 4 pasdbadmin.o.doctor_id 1
1 SIMPLE e eq_ref PRIMARY PRIMARY 4 pasdbadmin.o.event_id 1 Using index
1 SIMPLE tst ref order_id,test_id order_id 4 pasdbadmin.o.id 1
1 SIMPLE t eq_ref PRIMARY PRIMARY 4 pasdbadmin.tst.test_id 1
1 SIMPLE p eq_ref PRIMARY PRIMARY 4 pasdbadmin.o.patient_id 1
UPDATE:
Vấn đề dường như đã là một vấn đề với việc sử dụng bao gồm cả người sử dụng và bảng sự kiện trong truy vấn (không phải trong đó đã thực sự được sử dụng). Đây là mã sửa đổi thực thi nhanh hơn nhiều:
$q1 = "'";
$q2 = '"';
$order_id = "CONCAT(".$q2."<input type='hidden' id='order_id' value='".$q2.", o.id, ".$q2."'><a href='order_details.php?id=".$q2.", o.id, ".$q2."'><img src='https://pas.greysignal.com/img/search.png' border='0'></a> ".$q2.", o.id)";
$patient_name = "CONCAT(".$q2."<input type='hidden' id='patient_name' value='".$q2.", p.first_name, ' ', p.last_name, ".$q2."'><input type='hidden' id='patient_id' value='".$q2.", p.id, ".$q2."'><input type='hidden' id='patient_ssn' value='".$q2.", p.ssn, ".$q2."'><a href='patient_details.php?id=".$q2.", p.id, ".$q2."'><img src='https://pas.greysignal.com/img/search.png' border='0'></a> ".$q2.", p.first_name, ' ', p.last_name)";
$doc_name = "CONCAT(".$q2."<input type='hidden' id='doctor_name' value='".$q2.", d.first_name, ' ', d.last_name, ".$q2."'><input type='hidden' id='doctor_id' value='".$q2.", d.id, ".$q2."'><a href='doctor_details.php?id=".$q2.", d.id, ".$q2."'><img src='https://pas.greysignal.com/img/search.png' border='0'></a> ".$q2.", d.first_name, ' ', d.last_name)";
$order_date = "FROM_UNIXTIME(o.created_timestamp, '%m/%e/%Y')";
$tests = "GROUP_CONCAT(t.name SEPARATOR ', ')";
$aColumns = array($order_id, $order_date, $doc_name, $patient_name, $tests, 'o.status');
/* Indexed column (used for fast and accurate table cardinality) */
$sIndexColumn = "o.id";
/* DB table to use */
$sTable = "`orders` o, `patients` p, `doctors` d, `tests_ordered` tst, `tests` t";
$sWhere = "WHERE p.id = o.patient_id AND d.id = o.doctor_id AND tst.order_id = o.id AND t.id = tst.test_id";
$order_status = isset($_GET['status']) ? $_GET['status'] : 'all';
if($order_status == 'all'){
}else{
$sWhere .= " AND (o.status='Complete' OR o.status='$order_status')";
}
$sJoin = "";
$sGroupBy = "GROUP BY o.id";
/* Database connection information */
$gaSql['user'] = DB_USER;
$gaSql['password'] = DB_PASSWORD;
$gaSql['db'] = DB_NAME;
$gaSql['server'] = DB_SERVER;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* If you just want to use the basic configuration for DataTables with PHP server-side, there is
* no need to edit below this line
*/
/*
* MySQL connection
*/
$gaSql['link'] = mysql_pconnect($gaSql['server'], $gaSql['user'], $gaSql['password'] ) or
die('Could not open connection to server');
mysql_select_db($gaSql['db'], $gaSql['link']) or
die('Could not select database '. $gaSql['db']);
/*
* Paging
*/
$sLimit = "";
if (isset($_GET['iDisplayStart']) && $_GET['iDisplayLength'] != '-1')
{
$sLimit = "LIMIT ".mysql_real_escape_string($_GET['iDisplayStart']).", ".
mysql_real_escape_string($_GET['iDisplayLength']);
}
/*
* Ordering
*/
if (isset($_GET['iSortCol_0']))
{
$sOrder = "ORDER BY ";
for ($i=0 ; $i<intval($_GET['iSortingCols']) ; $i++)
{
if ($_GET[ 'bSortable_'.intval($_GET['iSortCol_'.$i]) ] == "true")
{
$sOrder .= $aColumns[ intval($_GET['iSortCol_'.$i]) ]."
".mysql_real_escape_string($_GET['sSortDir_'.$i]) .", ";
}
}
$sOrder = substr_replace($sOrder, "", -2);
if ($sOrder == "ORDER BY")
{
$sOrder = "";
}
}
/*
* Filtering
* NOTE this does not match the built-in DataTables filtering which does it
* word by word on any field. It's possible to do here, but concerned about efficiency
* on very large tables, and MySQL's regex functionality is very limited
*/
if ($_GET['sSearch'] != "")
{
$sWhere .= " AND (";
for ($i=0 ; $i<count($aColumns) ; $i++)
{
if($i!=4){ //skip tests column
$sWhere .= $aColumns[$i]." LIKE '%".mysql_real_escape_string($_GET['sSearch'])."%' OR ";
}
}
$sWhere = substr_replace($sWhere, "", -3);
$sWhere .= ')';
}
/* Individual column filtering */
for ($i=0 ; $i<count($aColumns) ; $i++)
{
if($i!=4){ //skip tests column
if ($_GET['bSearchable_'.$i] == "true" && $_GET['sSearch_'.$i] != '')
{
if ($sWhere == "")
{
$sWhere = "WHERE ";
}
else
{
$sWhere .= " AND ";
}
$sWhere .= $aColumns[$i]." LIKE '%".mysql_real_escape_string($_GET['sSearch_'.$i])."%' ";
}
}
}
/*
* SQL queries
* Get data to display
*/
$sQuery = "
SELECT SQL_CALC_FOUND_ROWS ".str_replace(" , ", " ", implode(", ", $aColumns))."
FROM $sTable
$sWhere
$sJoin
$sGroupBy
$sOrder
$sLimit
";
$filename = __DIR__.DIRECTORY_SEPARATOR."sql_log.txt";
file_put_contents($filename, $sQuery, FILE_APPEND);
$rResult = mysql_query($sQuery, $gaSql['link']) or die(mysql_error());
/* Data set length after filtering */
$sQuery = "
SELECT FOUND_ROWS()
";
$rResultFilterTotal = mysql_query($sQuery, $gaSql['link']) or die(mysql_error());
$aResultFilterTotal = mysql_fetch_array($rResultFilterTotal);
$iFilteredTotal = $aResultFilterTotal[0];
/* Total data set length */
$sQuery = "
SELECT COUNT(".$sIndexColumn.")
FROM $sTable
";
$rResultTotal = mysql_query($sQuery, $gaSql['link']) or die(mysql_error());
$aResultTotal = mysql_fetch_array($rResultTotal);
$iTotal = $aResultTotal[0];
//added to hide filtering
//$iTotal = $iFilteredTotal;
/*
* Output
*/
$output = array(
"sEcho" => intval($_GET['sEcho']),
"iTotalRecords" => $iTotal,
"iTotalDisplayRecords" => $iFilteredTotal,
"aaData" => array()
);
while ($aRow = mysql_fetch_array($rResult))
{
$row = array();
for ($i=0 ; $i<count($aColumns) ; $i++)
{
if ($aColumns[$i] != ' ')
{
/* General output */
$row[] = $aRow[$i];
}
}
$output['aaData'][] = $row;
}
echo json_encode($output);
Nếu tôi được sử dụng tham gia, truy vấn cập nhật sẽ là:
SELECT SQL_CALC_FOUND_ROWS
CONCAT("<input type='hidden' id='order_id' value='", o.id, "'><a href='order_details.php?id=", o.id, "'><img src='search.png' border='0'></a> ", o.id),
FROM_UNIXTIME(o.created_timestamp, '%m/%e/%Y'),
CONCAT("<input type='hidden' id='doctor_name' value='", d.first_name, ' ', d.last_name, "'><input type='hidden' id='doctor_id' value='", d.id, "'><a href='doctor_details.php?id=", d.id, "'><img src='search.png' border='0'></a> ", d.first_name, ' ', d.last_name),
CONCAT("<input type='hidden' id='patient_name' value='", p.first_name, ' ', p.last_name, "'><input type='hidden' id='patient_id' value='", p.id, "'><input type='hidden' id='patient_ssn' value='", p.ssn, "'><a href='patient_details.php?id=", p.id, "'><img src='search.png' border='0'></a> ", p.first_name, ' ', p.last_name),
GROUP_CONCAT(t.name SEPARATOR ', '),
o.status
FROM `orders` o
JOIN `doctors` d ON d.id = o.doctor_id
JOIN `patients` p ON p.id = o.patient_id
JOIN `tests_ordered` tst ON tst.order_id = o.id
JOIN `tests` t ON t.id = tst.test_id
WHERE o.status='Complete' OR o.status='Draft'
GROUP BY o.id
Vấn đề với điều này là DataTables chỉ không được thiết kế để hoạt động chính xác với JOINS khi sắp xếp và lọc được sử dụng do mảng cột, v.v. Tôi rất thích xem giải pháp có thể hoạt động với truy vấn như thế này.
add 'EXPLAIN' vào phía trước của các lựa chọn và xem những gì nó nói –
ngồi biên tập cho thấy kết quả của GIẢI THÍCH – compcentral
Hi i am cũng phải đối mặt với cùng một vấn đề + tìm kiếm của tôi cũng đang hiển thị hồ sơ thêm vì JOIN và nơi có điều kiện. .xin vui lòng bạn có thể giúp tôi ..http: //stackoverflow.com/questions/25015124/datatables-searching-at-server-side-php-mysql – user3209031