来自joomla的Mysql查询需要很长时间

时间:2016-03-02 04:55:32

标签: php mysql joomla

对不起这个问题。我不是一个优秀的程序员

Everything使用少量菜单项执行得很好。但有14K菜单项。我坚持这个查询。当我尝试访问

时会发生这种情况

administrator/index.php?option=com_modules&view=module&layout=edit&id=97 有没有办法改变查询??

查询

SELECT a.id    AS value, 
       a.title AS text, 
       a.alias, 
       a.level, 
       a.menutype, 
       a.type, 
       a.template_style_id, 
       a.checked_out 
FROM   gjb0e_menu AS a 
       LEFT JOIN `gjb0e_menu` AS b 
              ON a.lft > b.lft 
                 AND a.rgt < b.rgt 
WHERE  a.published != -2 
GROUP  BY a.id, 
          a.title, 
          a.alias, 
          a.level, 
          a.menutype, 
          a.type, 
          a.template_style_id, 
          a.checked_out, 
          a.lft 
ORDER  BY a.lft ASC 

Php代码

require_once JPATH_ADMINISTRATOR . '/components/com_menus/helpers/menus.php'; 
$menuTypes = MenusHelper::getMenuLinks();
        <ul class="treeselect">
            <?php foreach ($menuTypes as &$type) : ?>
            <?php if (count($type->links)) : ?>
                <?php $prevlevel = 0; ?>
                <li>
                    <div class="treeselect-item pull-left">
                        <label class="pull-left nav-header"><?php echo $type->title; ?></label></div>
                <?php foreach ($type->links as $i => $link) : ?>
                    <?php
                    if ($prevlevel < $link->level)
                    {
                        echo '<ul class="treeselect-sub">';
                    } elseif ($prevlevel > $link->level)
                    {
                        echo str_repeat('</li></ul>', $prevlevel - $link->level);
                    } else {
                        echo '</li>';
                    }
                    $selected = 0;
                    if ($this->item->assignment == 0)
                    {
                        $selected = 1;
                    } elseif ($this->item->assignment < 0)
                    {
                        $selected = in_array(-$link->value, $this->item->assigned);
                    } elseif ($this->item->assignment > 0)
                    {
                        $selected = in_array($link->value, $this->item->assigned);
                    }
                    ?>
                        <li>
                            <div class="treeselect-item pull-left">
                                <input type="checkbox" class="pull-left" name="jform[assigned][]" id="<?php echo $id . $link->value; ?>" value="<?php echo (int) $link->value; ?>"<?php echo $selected ? ' checked="checked"' : ''; ?> />
                                <label for="<?php echo $id . $link->value; ?>" class="pull-left"><?php echo $link->text; ?> <span class="small"><?php echo JText::sprintf('JGLOBAL_LIST_ALIAS', $this->escape($link->alias));?></span></label>
                            </div>
                    <?php

                    if (!isset($type->links[$i + 1]))
                    {
                        echo str_repeat('</li></ul>', $link->level);
                    }
                    $prevlevel = $link->level;
                    ?>
                    <?php endforeach; ?>
                </li>
                <?php endif; ?>
            <?php endforeach; ?>
        </ul>

这是创建查询的函数。

public static function getMenuLinks($menuType = null, $parentId = 0, $mode = 0, $published = array(), $languages = array())
{
    $db = JFactory::getDbo();
    $query = $db->getQuery(true)
        ->select('a.id AS value, a.title AS text, a.alias, a.level, a.menutype, a.type, a.template_style_id, a.checked_out')
        ->from('#__menu AS a')
        ->join('LEFT', $db->quoteName('#__menu') . ' AS b ON a.lft > b.lft AND a.rgt < b.rgt');

    // Filter by the type
    if ($menuType)
    {
        $query->where('(a.menutype = ' . $db->quote($menuType) . ' OR a.parent_id = 0)');
    }

    if ($parentId)
    {
        if ($mode == 2)
        {
            // Prevent the parent and children from showing.
            $query->join('LEFT', '#__menu AS p ON p.id = ' . (int) $parentId)
                ->where('(a.lft <= p.lft OR a.rgt >= p.rgt)');
        }
    }

    if (!empty($languages))
    {
        if (is_array($languages))
        {
            $languages = '(' . implode(',', array_map(array($db, 'quote'), $languages)) . ')';
        }

        $query->where('a.language IN ' . $languages);
    }

    if (!empty($published))
    {
        if (is_array($published))
        {
            $published = '(' . implode(',', $published) . ')';
        }

        $query->where('a.published IN ' . $published);
    }

    $query->where('a.published != -2')
        ->group('a.id, a.title, a.alias, a.level, a.menutype, a.type, a.template_style_id, a.checked_out, a.lft')
        ->order('a.lft ASC');

    // Get the options.
    $db->setQuery($query);

    try
    {
        $links = $db->loadObjectList();
    }
    catch (RuntimeException $e)
    {
        JError::raiseWarning(500, $e->getMessage());

        return false;
    }

    if (empty($menuType))
    {
        // If the menutype is empty, group the items by menutype.
        $query->clear()
            ->select('*')
            ->from('#__menu_types')
            ->where('menutype <> ' . $db->quote(''))
            ->order('title, menutype');
        $db->setQuery($query);

        try
        {
            $menuTypes = $db->loadObjectList();
        }
        catch (RuntimeException $e)
        {
            JError::raiseWarning(500, $e->getMessage());

            return false;
        }

        // Create a reverse lookup and aggregate the links.
        $rlu = array();

        foreach ($menuTypes as &$type)
        {
            $rlu[$type->menutype] = & $type;
            $type->links = array();
        }

        // Loop through the list of menu links.
        foreach ($links as &$link)
        {
            if (isset($rlu[$link->menutype]))
            {
                $rlu[$link->menutype]->links[] = & $link;

                // Cleanup garbage.
                unset($link->menutype);
            }
        }

        return $menuTypes;
    }
    else
    {
        return $links;
    }

1 个答案:

答案 0 :(得分:1)

您只需删除联接即可。我非常确定连接对您的查询完全没有影响,并且会更快。您可以尝试使用和不使用连接直接在数据库中运行查询,以验证结果是否相同。

我不确定这个联接的目的是什么,但我想这是程序员试图实现的某些功能的残余,但是这种情况有所不同或者掉线,留下了无用的连接。

这种分层表的结构是这样的,以防止这种类型的连接。你有一个lft和一个rgt值,并且在lft和rgt之间的任何项目都是一个子项目。此外,您还有一个级别值,告诉您树中的值有多深。因此,要选择项目的所有子项,您可以执行以下操作:

select * where lft>item.lft and rgt>item.rgt

要仅选择项目的直接后代,请执行

select * where lft>item.lft and rgt>item.rgt and level=item.level+1

数据库中的结构有点难以维护,需要特殊功能来更新数据,但搜索和提取数据的速度很快。

所以,你的getMenuLinks() - 函数应该像

一样开始
public static function getMenuLinks($menuType = null, $parentId = 0,
  $mode = 0, $published = array(), $languages = array())
{
  $db = JFactory::getDbo();
  $query = $db->getQuery(true)
    ->select('a.id AS value, a.title AS text, a.alias, a.level,
      a.menutype, a.type, a.template_style_id, a.checked_out')
    ->from('#__menu AS a');

  // Filter by the type
  if ($menuType) 
  ...