autocomplete slow with large database search - mysql

I've spent a considerable amount of time trying to track this one down. I've used a boxed autocomplete on my site (http://www.devbridge.com/projects/autocomplete/jquery/). As you type the word, it sends it as a GET variable to a page for processing where it is searched for in a mySQL database. The page looks like this:
$get = $_GET['query'];
$query = "SELECT title,author,id,isbn10,isbn13 FROM textbook
WHERE title LIKE '" . $get . "%'
OR author LIKE '" . $get . "%'
LIMIT 5
";
$result = mysql_query($query,$connection);
$resString = "";
$idString = "";
while($data = mysql_fetch_array($result)){
$resString .= "'" . title($data['title']) . " by " . $data['author'] . "',";
$idString .= "'" . $data['id'] . "',";
}
$resString = rtrim($resString, ',');
$idString = rtrim($idString, ',');
$code = "{\n";
$code .= "query:'" . $get . "',\n";
$code .= "suggestions:[" . $resString . "],\n";
$code .= "data:[" . $idString . "]\n";
$code .= "}";
echo $code;
This outputs a basic JSON dataset that is read and shot back as a result. The problem is that it has been REALLY slow. the "LIMIT 5" helped a ton to speed it up some. However, still running slow after the initial result set shows. I may type in "hum" and it will come back with a quick result set, but any letters/words after that take 4-6 seconds to show. The database is 300K records roughly. Attached is a picture of my database structure page:
database http://semesterkey.com/images/data.jpg
Im just trying to figure out how to speed things up. I think it might be my database structure, it could be how Im querying? I just have no idea. Thanks in advance for your help!

There is only solution is that use Indexing on column which you want to show in autocomplete in your Database, hope this will help you

Yes, the answer to your problem is an index on the (author, title) group of columns. It will grow the amount of space used by the DB and will decrease the performance on INSERT, UPDATE, DELETE in that table, but it will increase the interrogation performance.

make index on author and title may help you to improve the performance.

Syntax help for those who don't grasp which above answer
ALTER TABLEYour_table_nameADD INDEX (column_title) ;

Related

Trying to put a player name with apostrophe in href

My problem is the next, im having troubles with some names. My application is getting out from database all the names of a team and then i put them in a link (A href) to pass by GET the player name and then charge the stadistics. The code is the next:
$sele_t5 = "SELECT * FROM PLAYERS WHERE nom_team='$team' ORDER BY totalpoints DESC LIMIT 5;";
$sele_t5 = mysql_query( $sele_t5, $link );
while( $row = mysql_fetch_assoc( $sele_t5 ) )
{
echo "<TR>";
echo "<TD ALIGN='CENTER'><A HREF='?player={$row['nombre']}'>".$row['nombre']."</A></TD>";
}
well this is working perfect with all the players except with names with apostrophe, for example:
Jo. O'Brien when i press the link (which show me the full name correct) i got Jo. O in adress bar, is like the apostrophe is cutting the action. Happens the same when i send some name with apostrophe by post, so i would appreciate any solve for this problem.
thanks and best regards,
Change
echo "<TD ALIGN='CENTER'><A HREF='?player={$row['nombre']}'>"
to
echo "<TD ALIGN='CENTER'><A HREF='?player=" . urlencode($row['nombre']) . "'>"
However, you should really read about MySQL-Injections and Cross-Site-Scripting or you will run into big security issues.

Left Join Drupal 7

I have this problem regarding Drupal 7 Mysql queries especially on LEFT JOIN.
I found this solution but I can't seem it apply it on my problem since I'm not aware how the syntax goes.
https://drupal.stackexchange.com/questions/4317/how-do-i-write-a-left-join-query
This is the solution that I found on the link above.
$terms = db_select('taxonomy_index', 'ti')
->fields('ti', array('tid', 'name'))
->leftJoin('taxonomy_term_data', 'ttd', 'ti.tid = ttd.tid')
->condition('vid', 2)
->condition('nid', $nid)
->execute();
foreach ($terms as $term) {
// $term contains the object for the taxonomy term.
}
Yet I'm having a problem on how do I apply it to my query.
Here is my LEFT JOIN query on mysql.
$query = "SELECT sweep_table.end_offer, sweep_table.title, embed.fbp_id, embed.sweep_stat
FROM sweep_table, embed
WHERE sweep_table.uid=embed.uid AND sweep_table.promo_id=embed.sweep_id";
I already did the first few lines but the rest, I don't know how.
$terms = db_select('sweep_table', 'embed')
->fields('sweep_table', array('end_offer', 'title'))
->fields('embed', array('fbp_id', 'sweep_stat'))
->leftJoin('taxonomy_term_data', 'ttd', 'ti.tid = ttd.tid') //Don't know how to apply to my query.
->condition('vid', 2)
->condition('nid', $nid)
->execute();
foreach ($terms as $term) {
}
Also, was wondering how do I retrieve the data after I successfully LEFT JOIN it?
Would be glad if you help me guys.
Wouldn't have thought that this would work though. Thanks to rekire for the hint.
$query = "SELECT sweep_table.end_offer, sweep_table.title, embed.fbp_id, embed.sweep_stat FROM sweep_table, embed WHERE sweep_table.uid=embed.uid AND sweep_table.promo_id=embed.sweep_id";
$result = db_query($query);
foreach ($result as $row) {
echo $row->end_offer . " " . $row->title . " " . $row->fbp_id . " " . $row->sweep_stat . "<br>";
}

How to remove width and height attributes from multiple posts in Wordpress (MySQL)

So I have thousands of Wordpress posts with the width and height attributes which I want to remove. For example:
img class="aligncenter size-full wp-image-21011999" title="sometitle"
alt="somealt" src="http://mysite.com/blabla/somefile.jpg" width="xxx" height="xxx"
As i mentioned i want to remove width="xxx" height="xxx" and i want to remove them directly from MySQL, dont want to use any PHP functions or similar.
Is there a query i can run through PhpMyadmin?
Are there any regex i can use for the xxx which is different for each post.
Thank you!
You can write a small PHP script (outside of WordPress of course) that will accomplish this quite easily using Regex.
<?php
$host = "hostname";
$user = "username";
$pass = "password";
$db = "database";
mysql_connect($host, $user, $pass);
mysql_select_db($db);
$pattern = "/width|height=\"[0-9]*\"/";
$query = "SELECT ID, post_content FROM wp_posts";
while ($row = mysql_fetch_assoc($query)) {
if (preg_match($pattern, $row['post_content']))
{
$row['post_content'] = preg_replace($pattern, "", $row['post_content']);
mysql_query("UPDATE wp_posts SET post_content=" . $row['post_content'] . "WHERE ID=" . $row['ID'];
}
}
?>
That's the way I'd do it anyway. I'm assuming when you said "no PHP functions" that you mean that you want the data permanently updated in the database, rather than just updated on the fly every time the page is loaded. This should solve the issue. Writing a raw SQL query to deal with this problem will likely be much more complicated.
You don't need to do this within WordPress. You could even run this on a different host, provided said host has database access.
Note: I haven't tested any of this. If you use it, I'd make sure to run it on a small subsection of your database before applying it sitewide.
I have used this script and it has some errors. I have corrected them and used it. It works. Make sure the table name (wpfs_posts) correspondents to your table name with posts. Always have a backup off course.
<?php
$host = "localhost";
$user = "nameuser";
$pass = "password";
$db = "namedb";
mysql_connect($host, $user, $pass);
mysql_select_db($db);
$pattern = "/width|height=\"[0-9]*\"/";
$query = "SELECT ID, post_content FROM wpfs_posts";
$result = mysql_query($query);
while ($row = mysql_fetch_assoc($result)) {
if (preg_match($pattern, $row['post_content']))
{
$row['post_content'] = preg_replace($pattern, "", $row['post_content']);
$row['post_content']=mysql_real_escape_string($row['post_content']);
mysql_query("UPDATE wpfs_posts SET post_content='" . $row['post_content'] . "' WHERE ID=" . $row['ID']);
}
}
?>

Narrow search results from mysql database keywords

I have a large database containing part numbers for a filter company. Several of the products have similar years and model numbers. I have a php script that is searching a text keyword section for each part.
So for a 1997-1999 Honda Crf 250 090987 19.95 the keywords are:
1997 1998 1999 honda crf 250 090987
I got the code from a tutorial and it's written to search the keywords section for everything separated by a space. The problem is that a lot of the listings have honda or similar year spreads.
I need to figure out how to alter the php to narrow the results so if someone types "1997 honda", all of the hondas and '97s don't show up but only ones that are 1997 hondas.
I'm new to php and I've looked all around and can't figure it out. Any help will be thoroughly appreciated.
here's the php:
$keywords = $_GET['keywords'];
$terms = explode(" ", $keywords);
$query = "SELECT * FROM search WHERE ";
foreach ($terms as $each){
$i++;
if ($i == 1)
$query .= "keywords LIKE '%$each%' ";
else
$query .= "OR keywords LIKE '%$each%' ";
}
// connect
mysql_connect("localhost", "root", "root");
mysql_select_db("catalog");
$query = mysql_query($query);
$numrows = mysql_num_rows($query);
if ($numrows > 0){
while ($row = mysql_fetch_assoc($query)){
$id = $row['id'];
$year = $row['year'];
$manufacturer = $row['manufacturer'];
$product = $row['product'];
$partnumber = $row['partnumber'];
$price = $row['price'];
echo "<div id=\"results\">
<div class=\"words\">$year</div><div class=\"words\">$manufacturer</div><div class=\"words\">$product</div><div class=\"words\">$partnumber</div>$price<br /></div>";
}
}
else
echo "<div class=\"no_results\"><center>No results found for \"<b>$keywords</b>\"</center></div>";
// disconnect
mysql_close();
?>
Interesting problem.
I thought of 2 approaches:
(1) if you have control over the database structure, you could SELECT WHERE (make = 'Honda' AND Year IN (1997,1998,1999)) AND the "like" stuff you already have (without the make/year). But you would need to separate out the model years and make into separate fields.
(2) otherwise, if we can assume the input is always "year(s) make [other keywords], we could do what izuriel suggested while I was typing this, just "AND 'keywords = '1997' AND keywords = 'honda' AND (our existing list of "like" clauses)".
that way you'd get only 1997 Hondas that have any or all of the other keywords.
Use AND in the query instead of OR to enforce that all keywords must match, otherwise one keyword match will return a result always. Outside of that, you'll have to do some Relevance work in code which might slow down the application.
I recommend you to use one symbol percentage at the end of the word and you and instead of or and you limit in your query if the database is large

PHP Array Duplicates

my first post here and hoping someone can help. I am querying a table in a mySQL DB, and obviously getting the results. However, the table is used to store multiple entry by one user for the purpose of user contacts.
What I would like to do is display each user individually, and count the number of contacts each user has. I had a look at the post "How to detect duplicate posts in PHP array, which helped a bit, but I am still stuck.
Please see my code for the query below, I have left out the array duplicate part as it is a pretty mess at the moment.
<?php
$result = mysql_query("SELECT * FROM vines");
while($row = mysql_fetch_array($result)) {
$results=$row['vinename'];
echo $results;
echo "<br />";
}
?>
This result returns the below, obviously these are records from the vinename coloumn.
Marks Vine<br />
Marks Vine<br />
Marks Vine<br />
Tasch Vine<br />
Tasch Vine<br />
Regards
Mark Loxton
Hi there, my first post here and hoping someone can help. I am querying a table in a mySQL DB, and obviously getting the results. However, the table is used to store multiple entry by one user for the purpose of user contacts.
You can do this in the query itself a lot more easily than in the PHP code afterwards.
SELECT name, COUNT(id) AS count FROM vines GROUP BY name
Just change the SQL Query to
SELECT vinename, COUNT(vinename) as counter FROM vines GROUP BY vinename
and then do
echo $row['vinename']." #".$row['counter']."<br />";
I would run two types queries...
1) Select each UNIQUE user from vines.
2) For each user in that set, run a second COUNT query against that user's id in the table "vines".
I hope that helps.
You can create a separate array to store records you've already output there.
<?php
$result = mysql_query("SELECT * FROM vines");
$duplicates = array(); ## store duplcated names here
while($row = mysql_fetch_array($result)) {
$results = $row['vinename'];
if (!array_key_exists($results, $duplicates)) {
echo $results;
echo "<br />";
$duplicates[$results] = 1; ## mark that we've already output this records
}
}
?>
You can try, change your query to use count and group of SQL.
Somoe thing like
$result = mysql_query("SELECT count(*) as total,name FROM vines GROUP by name");
firstly thank you everyone for such awesome input. I seriously did not expect such a quick response. I am seriously grateful.
I used the recommendation from Jitter. I have pretty much been going through so many variations of the above code today, but just needed that missing piece.
Thanks, everyone. Below is what the final code looks like for anyone else who has the same problem in the future.
<?php
$result = mysql_query("SELECT vinename, COUNT(vinename) as counter FROM vines GROUP BY vinename ORDER BY counter DESC LIMIT 0, 3");
while($vinerow = mysql_fetch_array($result))
echo $vinerow['vinename']." has ".$vinerow['counter']." tomatos."."<br />";
?>
change your query to:
SELECT distinct * FROM vines