MariaDB Inner join is slow - performance

Here is my SQL (with explain):
EXPLAIN
UPDATE
VF_KRED kred
INNER JOIN GBI gbi ON
kred.vendor = gbi.vendor
INNER JOIN MASTER_DATA master_data ON
master_data.vendor_code = gbi.vendor
SET
kred.GBI_VAL_REP =
(CASE
WHEN kred.country = 'JP' THEN
CASE
WHEN gbi.WITHHOLD_TAX_CODE = 0 THEN 2
WHEN gbi.WITHHOLD_TAX_CODE = 'IN' THEN 1
END
ELSE
CASE
WHEN gbi.WITHHOLD_TAX_CODE = master_data.REDUCED_RATE THEN
CASE
WHEN gbi.WITHHOLD_TAX_CODE = 0 THEN 3
WHEN gbi.WITHHOLD_TAX_CODE BETWEEN 1 AND 19 THEN 4
END
ELSE 5
END
END);
Giving below the outcome:
Now, the UPDATE SQL takes ~6+ minutes.
Below are the indexes on tables:
VF_KRED table:
GBI table:
MASTER_DATA table:
VENDOR columns are all varchar(25) type.
-- EDIT: (describing whole table structure below):
SHOW CREATE TABLE GBI;
CREATE TABLE `GBI` (
`VENDOR` varchar(25) CHARACTER SET utf8 NOT NULL,
`COMPANY_CODE` varchar(5) CHARACTER SET latin1 NOT NULL DEFAULT '',
`VENDOR_NAME` varchar(100) CHARACTER SET utf8 NOT NULL DEFAULT '',
`WITHHOLD_TAX_TYPE` varchar(2) CHARACTER SET latin1 NOT NULL DEFAULT '',
`WITHHOLD_TAX_CODE` varchar(2) CHARACTER SET latin1 NOT NULL DEFAULT '',
`DOCUMENT_CURRENCY` varchar(4) CHARACTER SET latin1 NOT NULL DEFAULT '',
`CREATE_DT` datetime NOT NULL,
PRIMARY KEY (`VENDOR`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SHOW CREATE TABLE VF_KRED;
CREATE TABLE `VF_KRED` (
`VENDOR` varchar(25) CHARACTER SET latin1 NOT NULL,
`COUNTRY_CODE` varchar(5) CHARACTER SET latin1 DEFAULT NULL,
`COUNTRY` varchar(3) CHARACTER SET latin1 DEFAULT NULL,
`SEARCH_TERM` varchar(100) CHARACTER SET latin1 DEFAULT NULL,
`CREATE_DT` datetime DEFAULT NULL,
`GBI_VAL_REP` int(11) NOT NULL DEFAULT 5,
PRIMARY KEY (`VENDOR`),
KEY `vf_kred` (`GBI_VAL_REP`),
KEY `VF_KRED_COUNTRY_IDX` (`COUNTRY`) USING BTREE,
CONSTRAINT `vf_kred_ibfk_1` FOREIGN KEY (`GBI_VAL_REP`) REFERENCES `VENDOR_RATE_CATEGORY` (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
SHOW CREATE TABLE MASTER_DATA;
CREATE TABLE `MASTER_DATA` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`VENDOR_CODE` varchar(25) CHARACTER SET latin1 DEFAULT NULL,
`VENDOR_NAME` varchar(2000) CHARACTER SET latin1 DEFAULT NULL,
`COUNTRY` varchar(2) CHARACTER SET latin1 DEFAULT NULL,
`APPLN_RECEIVED_FROM_US` datetime DEFAULT NULL,
`ITUNES_CONTRACT_NUM` varchar(2000) CHARACTER SET latin1 DEFAULT NULL,
`CONTRACT_EFFECTIVE_DT` datetime DEFAULT NULL,
`CONTRACT_EXPIRATION_DT` datetime DEFAULT NULL,
`AUTO_RENEWAL` varchar(10) CHARACTER SET latin1 DEFAULT NULL,
`REDUCED_RATE` int(11) DEFAULT NULL,
`FORM_17` varchar(45) CHARACTER SET latin1 DEFAULT NULL,
`RESIDENCY_CERT_ISSUE_DT` datetime DEFAULT NULL,
`TAX_AUTHORITY_SUBMISSION_DT` datetime DEFAULT NULL,
`TAX_AUTHORITY_ACCEPTANCE_DT` datetime DEFAULT NULL,
`STATUS` varchar(45) CHARACTER SET latin1 DEFAULT NULL,
`FORM_17_EXPIRATION` varchar(45) CHARACTER SET latin1 DEFAULT NULL,
`COMMENTS` varchar(2000) CHARACTER SET latin1 DEFAULT NULL,
`REMARKS` varchar(2000) CHARACTER SET latin1 DEFAULT NULL,
`CATEGORY` varchar(45) CHARACTER SET latin1 DEFAULT NULL,
PRIMARY KEY (`ID`),
KEY `MASTER_DATA_VENDOR_CODE_IDX` (`VENDOR_CODE`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2369 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
Any clues?

Do not mix CHARACTER SETs (or datatypes or collations) on columns that need to be compared, as in a JOIN. Note how vendor is latin1 versus utf8. This slows down the JOIN. (Also, check vendor_code due to another join.)
The clue in EXPLAIN: "func". This implied that somehow vendor was being modified in order to perform the JOIN. The CREATE TABLE showed that the charset was different.
128MB for innodb_buffer_pool_size is find, even advisable, if you have only 1GB of RAM. For 8GB, 6G would be a better setting. By increasing the value, you will probably cut back on the I/O necessary to run this, and other, queries. Again, this impacts the speed of the JOIN.

Related

How to configure Oracle Column's DefaultValue And Collate Value

In Oracle 19c, I want to specify the default value of a column and the collate property at the same time.
create table id_table(
name varchar2(64) collate binary_ai,
id varchar2(8) collate binary_ci
);
insert into id_table values('Christopher', 'ABCD1234');
SELECT collation(name), collation(id) from id_table;
COLLATION(NAME)
COLLATION(ID)
BINARY_AI
BINARY_CI
It was well specified as intended.
but,
create table id_table2(
name char default 'Y' collate binary_ai,
id varchar2(8)
);
insert into id_table2 values('c', 'ABCD1234');
SELECT collation(name), collation(id) from id_table2;
COLLATION(NAME)
COLLATION(ID)
USING_NLS_COMP
USING_NLS_COMP
If you specify the default value and collate together, an unintended value is specified.
The intent was to expect the same values as in the first example.
Are DEFAULT VALUE and COLLATE mutually exclusive?

Laravel how to get list of related fields through pivot table

I have 4 tables : peoples, companies, countries and the pivot table company_people (as peoples & companies both belongs to many) which has both people_id and company_id.
In the People model, I have the following functions:
class People extends Model
{
// main company (only one)
public function company()
{
return $this->belongsTo(Company::class);
}
// all other companies
public function companies()
{
return $this->belongsToMany(Company::class);
}
public function country()
{
return $this->belongsTo(Country::class);
}
}
Then in the People controller, I have the following in order to prepare to display a list of all the peoples with the related main company name (only one), country name (only one) and other companies as a list of names. I can do the first 2 but not the last one. How can I do that?
$peoples = People::orderBy($sortField,$sortOrder)
->with(['companies','company','country'])
->get();
foreach ($peoples as $people) {
$people->company = '['.$people->company->company.']'; // main company name
$people->country = '['.$people->country->country.']'; // country name
$people->otherCompanies = ? // list of other company names through pivot table
}
And here all the structure of the 4 tables:
CREATE TABLE `company_people` (
`id` bigint NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`company_id` bigint UNSIGNED NOT NULL,
`people_id` bigint UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `countries` (
`id` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'AA',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`is_active` int NOT NULL DEFAULT '1',
`country` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `peoples` (
`id` bigint UNSIGNED NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`is_active` int NOT NULL DEFAULT '1',
`firstname` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`lastname` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '',
`country_id` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'ZA',
`company_id` bigint UNSIGNED DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci PACK_KEYS=0;
ALTER TABLE `company_people`
ADD PRIMARY KEY (`id`),
ADD KEY `article_id` (`company_id`),
ADD KEY `tag_id` (`people_id`);
ALTER TABLE `countries`
ADD PRIMARY KEY (`id`);
ALTER TABLE `peoples`
ADD PRIMARY KEY (`id`),
ADD KEY `country_id` (`country_id`),
ADD KEY `company_id` (`company_id`);
ALTER TABLE `company_people`
MODIFY `id` bigint NOT NULL AUTO_INCREMENT;
ALTER TABLE `peoples`
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `peoples`
ADD CONSTRAINT `peoples-company` FOREIGN KEY (`company_id`) REFERENCES `companies` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `peoples-country` FOREIGN KEY (`country_id`) REFERENCES `countries` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
ALTER TABLE `companies`
ADD CONSTRAINT `peoples-country` FOREIGN KEY (`country_id`) REFERENCES `countries` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
ALTER TABLE `company_people`
ADD CONSTRAINT `companies-peoples` FOREIGN KEY (`company_id`) REFERENCES `companies` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `peoples-companies` FOREIGN KEY (`people_id`) REFERENCES `peoples` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
you can use pluck() to get all the company name then toArray() to convert in array like this
$peoples = People::orderBy($sortField,$sortOrder)
->with(['companies','company','country'])
->get();
foreach ($peoples as $people) {
$people->company = '['.$people->company->company.']'; // main company name
$people->country = '['.$people->country->country.']'; // country name
$people->otherCompanies = $people->companies->pluck('name')->toArray(); // list of other company names through pivot table
}
And if you want otherCompanies name as comma seprate then use $people->companies->pluck('name')->join(',');

Laravel - Eloquent query to display Quiz Result

I am trying to write a query in my controller to display Quiz result for students. I have these tables
CREATE TABLE IF NOT EXISTS `quizz_question` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`topic` varchar(1000) COLLATE utf8_unicode_ci NOT NULL,
`question_code` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`answer1` varchar(100) COLLATE utf8_unicode_ci NULL,
`answer2` varchar(100) COLLATE utf8_unicode_ci NULL,
`answer3` varchar(100) COLLATE utf8_unicode_ci NULL,
`answer4` varchar(100) COLLATE utf8_unicode_ci NULL,
`topic` varchar(1000) COLLATE utf8_unicode_ci NOT NULL,
`correct_answer` varchar(100) COLLATE utf8_unicode_ci NULL,
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=10 ;
CREATE TABLE IF NOT EXISTS `quizz_attempt` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`student_code` varchar(1000) COLLATE utf8_unicode_ci NOT NULL,
`answer` varchar(100) COLLATE utf8_unicode_ci NULL,
`question_code` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=10 ;
The two tables became these two model classes: QuizzQuestion and QuizAttempt.
In quizz_attempt, if a student select an answer (answer), it will take answer and question_code in quizz_attempt and compare with quizz_question.
quizz_attempt.answer = 1 then it will choose the content in answer1 as correct answer
quizz_attempt.answer = 2 then it will choose the content in answer2 as correct answer
quizz_attempt.answer = 3 then it will choose the content in answer3 as correct answer
quizz_attempt.answer = 4 then it will choose the content in answer4 as correct answer
public function gameQualifiers(Request $request)
{
$revenuedetails = DB::table('quizz_attempt as g')
->select(
'g.student_code',
'g.answer'
)
->orderByRaw('g.created_at DESC');
}
I know I need to join the two tables for the result. I started the code in my controller, but don't know how to complete it. i want to write a query to display list of students who choose correct answers
The quiz attempt should have the quizz_question_id as a Foreign Key. This will make it easier down the line to have the two connected.
You can set up two models to match your database tables: QuizzQuestion and QuizzAttempt. You can set up Foreign Keys like so:
QuizzAttempt.php
public function quizzQuestion()
{
return $this->belongsTo('App\QuizzQuestion');
}
And QuizzQuestion.php
public function quizzAttempts()
{
return $this->hasMany('App\QuizzQuestion');
}
So now, you want to get all of the attempts where the answer is correct - you are looking at an instance of QuizzQuestion, e.g.
$question = QuizzQuestion::find(1); // first question
$correctResults = QuizzAttempts::where('quizz_question_id', $question->id)
->where('answer', $question->correct_answer)
->pluck('student_code');`
Now you have all the student codes of the students that got the correct answers.
*** Update
If you cannot change the structure of the tables, you can run the following query:
// 1) find the question you want the answers for
$question = QuizzQuestion::find(1);
// 2) retrieve the correct results
$correctResults = QuizzAttempts::where('question_code', $question->question_code)
->where('answer', $question->correct_answer)
->pluck('student_code');`

Joomla migration issue

I have transferred my website to a new server after updating the files and database I am getting this issue
Table 'jimcorbe_jimcorbe.xpivg_session' doesn't exist SQL=INSERT INTO xpivg_session (session_id, client_id, time) VALUES ('18f0b96cfc5e1cb723b8405137ff36a6', 0, '1427709725')
I am very new to joomla so could not understand what it means. Can anyone provide me with the solution to get back my website live.
During the migration, it's possible that database table prefixes have changed.
Open PhpMyAdmin and look for the session table. If it doesn't exist, run the following SQL command:
CREATE TABLE IF NOT EXISTS `xpivg_session` (
`session_id` varchar(200) NOT NULL DEFAULT '',
`client_id` tinyint(3) unsigned NOT NULL DEFAULT '0',
`guest` tinyint(4) unsigned DEFAULT '1',
`time` varchar(14) DEFAULT '',
`data` mediumtext,
`userid` int(11) DEFAULT '0',
`username` varchar(150) DEFAULT '',
`usertype` varchar(50) DEFAULT '',
PRIMARY KEY (`session_id`),
KEY `whosonline` (`guest`,`usertype`),
KEY `userid` (`userid`),
KEY `time` (`time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

codeigniter join problem

Hello all i have a problem that when i try to join my comment table it show nothing
here is my code
$this->db->select('*,users.profil_billed as profil_billed, forum_traad.id as traad_id');
$this->db->from('forum_traad');
$this->db->join('users', 'forum_traad.brugernavn = users.username');
$this->db->where('forum_traad.fk_forum_kategori', $id);
$this->db->join('forum_kommentare', 'forum_traad.id = forum_kommentare.fk_forum_traad');
$this->db->where('forum_kommentare.fk_forum_traad', 'forum_traad.id');
$this->db->order_by("forum_traad.id", "DESC");
its then i put this in it show nothing, and i dont know why.. do i need some left join, right join etc.? i have try all of it :d
$this->db->join('forum_kommentare', 'forum_traad.id = forum_kommentare.fk_forum_traad');
$this->db->where('forum_kommentare.fk_forum_traad', 'forum_traad.id');
kommentare = comments
traad = thread
brugernavn = username
kategori = categori
its danish,
sorry my bad english hope some one can help me out
my database structure is this and im using mysql
CREATE TABLE `forum_kategori` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`kategori` text NOT NULL,
`beskrivelse` mediumtext NOT NULL,
`godkendt` varchar(4) NOT NULL DEFAULT 'ja',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=10;
CREATE TABLE `forum_kommentare` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`fk_forum_traad` int(11) NOT NULL,
`brugernavn` text NOT NULL,
`indhold` mediumtext NOT NULL,
`dato` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`time` text NOT NULL,
`godkendt` varchar(4) NOT NULL DEFAULT 'ja',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=28;
CREATE TABLE `forum_traad` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`overskrift` text NOT NULL,
`indhold` mediumtext NOT NULL,
`fk_forum_kategori` int(11) NOT NULL,
`brugernavn` text NOT NULL,
`dato` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`godkendt` varchar(4) NOT NULL DEFAULT 'ja',
`time` text NOT NULL,
`status` varchar(8) NOT NULL DEFAULT 'aaben',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=4;
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(80) NOT NULL,
`password` text NOT NULL,
`kon` varchar(5) NOT NULL,
`alder` text NOT NULL,
`hood` varchar(4) DEFAULT NULL,
`fornavn` varchar(60) DEFAULT NULL,
`efternavn` varchar(100) DEFAULT NULL,
`city` text,
`ip` varchar(20) DEFAULT NULL,
`level` text,
`email` text,
`point` int(11) NOT NULL,
`oprettet` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`fritekst` mediumtext NOT NULL,
`profil_billed` text NOT NULL,
`online` varchar(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=31;
and it return nothing and no errors it only show a message i have done with a else statement that said "there is no threads on this categori", i have try with left join, right join inner join full join, ye all of it :S
You should try using a left join on your joins and work from there. If that doesn't work then there isn't a link between the tables.
Try this code:
$this->db->select('*,users.profil_billed as profil_billed, forum_traad.id as traad_id');
$this->db->from('forum_traad');
$this->db->join('users', 'forum_traad.brugernavn = users.username');
$this->db->join('forum_kommentare', 'forum_traad.id = forum_kommentare.fk_forum_traad');
$this->db->where('forum_traad.fk_forum_kategori', $id);
$this->db->order_by("forum_traad.id", "DESC");
You can use after $this->db->get() the
print $this->db->last_query();
and check what's wrong.

Resources